jonobr1 / two.js

A renderer agnostic two-dimensional drawing api for the web.
https://two.js.org
MIT License
8.31k stars 455 forks source link

How can I add events on dynamic canvas element #544

Closed PranjalVyas1507 closed 3 years ago

PranjalVyas1507 commented 3 years ago

I have dynamic elements in my app (div tag with renderer type canvas, on which the Two constructor appends), Every time the element is added I want to display the properties of the said element through an alert dialog or a ticker.

I have tried addEventListener but that does not work. Here a snippet of my code below:

  var elem = document.getElementById('NN_park');
       var elem = $("#NN-visualizer").getElementById("NeuralPark");

            var two = new Two({
            type: Two.Types.canvas,
             width: 1300, height: 900
            // fullscreen:
        }).appendTo(elem);

        var colors = [
            'rgb(255, 64, 64)',
            'rgb(0, 128, 64)',
            'rgb(0, 200, 255)',
            'rgb(135, 90, 68)',
            'rgb(153, 75, 55)',
            'rgb(255, 50, 0)'
        ];
        colors.index = 0;

        var radius = 20;
        var radialGradient = two.makeRadialGradient(
            0, 0,
            radius,
            new Two.Stop(0, 'rgba(255, 100, 74, 1)', 1),
            new Two.Stop(1, 'rgba(0, 0, 128, 250)', 0)
        );

        addlayer(default_layers,default_neurons) ;

        two.update();

        function addneuron(x,y,r)
        {
            var circle = two.makeCircle(x, y, r);

            circle.fill = radialGradient ;
            circle.stroke = 'blue';
            circle.linewidth = 2.5;

            circle.addEventListener('mouseover',showTicker(event),false);

            two.bind('update', function(frameCount, timeDelta) {
                circle.rotation = frameCount / 60;
            });

            two.play();

Here the addlayer function would call the addneuron function

jonobr1 commented 3 years ago

If you use the SVG Renderer instead of Canvas (e.g: Two.Types.svg) then you can setup the event listeners like this: https://two.js.org/examples/svg-events.html

Unfortunately there are not event listeners on objects out-of-the-box with Two.js

joex92 commented 3 years ago

I have dynamic elements in my app (div tag with renderer type canvas, on which the Two constructor appends), Every time the element is added I want to display the properties of the said element through an alert dialog or a ticker.

I have tried addEventListener but that does not work. Here a snippet of my code below:

  var elem = document.getElementById('NN_park');
       var elem = $("#NN-visualizer").getElementById("NeuralPark");

            var two = new Two({
            type: Two.Types.canvas,
             width: 1300, height: 900
            // fullscreen:
        }).appendTo(elem);

        var colors = [
            'rgb(255, 64, 64)',
            'rgb(0, 128, 64)',
            'rgb(0, 200, 255)',
            'rgb(135, 90, 68)',
            'rgb(153, 75, 55)',
            'rgb(255, 50, 0)'
        ];
        colors.index = 0;

        var radius = 20;
        var radialGradient = two.makeRadialGradient(
            0, 0,
            radius,
            new Two.Stop(0, 'rgba(255, 100, 74, 1)', 1),
            new Two.Stop(1, 'rgba(0, 0, 128, 250)', 0)
        );

        addlayer(default_layers,default_neurons) ;

        two.update();

        function addneuron(x,y,r)
        {
            var circle = two.makeCircle(x, y, r);

            circle.fill = radialGradient ;
            circle.stroke = 'blue';
            circle.linewidth = 2.5;

            circle.addEventListener('mouseover',showTicker(event),false);

            two.bind('update', function(frameCount, timeDelta) {
                circle.rotation = frameCount / 60;
            });

            two.play();

Here the addlayer function would call the addneuron function

  • Code is being run on an electron app
  • OS: Windows 10

I believe that for canvas you should be listening to the mouse position all the time and comparing it with the element in canvas position and size to trigger events, otherwise there's no way to do it... so yeah, better use SVG instead of Canvas... also because listening to the mouse position and calculating its distance with all elements on canvas is too much use of resources...

If you use the SVG Renderer instead of Canvas (e.g: Two.Types.svg) then you can setup the event listeners like this: https://two.js.org/examples/svg-events.html

Unfortunately there are not event listeners on objects out-of-the-box with Two.js

What about the .listen(obj, name,handler) method? isn't that for events? I found out about that method doing tests, but idk how to use it, there is no doc on that...

this is my solution for events:

document.getElementById(shape.id).onclick = (ev) => {
console.log(ev); // do something when clicked
} 

I was expecting something like:

shape.element.onclick = (ev) => {
console.log(ev); // do something when clicked
} 

or

shape.event["click"] = (ev) => {
console.log(ev); // do something when clicked
} 

but doing shape._renderer.elem.[event] seems unnatural... and using the document.getElementById method is like coding too much... idk, just an opinion...

jonobr1 commented 3 years ago

Thanks for your input. But, the ray casting and pointer events I'd like to add will be renderer agnostic, which none of the solutions you presented are.

The API of event systems will ultimately be the way this functionality is exposed like shape.bind("click", callback);. It just doesn't exist yet.

PranjalVyas1507 commented 3 years ago

If you use the SVG Renderer instead of Canvas (e.g: Two.Types.svg) then you can setup the event listeners like this: https://two.js.org/examples/svg-events.html

Unfortunately there are not event listeners on objects out-of-the-box with Two.js

Used SVG. Your solution works. Thank you.