pts icon indicating copy to clipboard operation
pts copied to clipboard

Can events be bound to a different element?

Open chrisui opened this issue 4 years ago • 8 comments

Ie. Render in a child canvas but bind events to parent div.

This would allow for easily overlaying the canvas with interactive dom elements.

chrisui avatar Jan 11 '20 16:01 chrisui

Note I've also tried passing the parent element to quickStart which means Pts creates and manages the canvas element for me. However it seems that the event bindings are still made on the canvas rather than the parent element (a div in this case).

chrisui avatar Jan 11 '20 22:01 chrisui

See http://chrispearce.co/ for my example of the issue :) And code here: https://github.com/chrisui/chrispearce.co/blob/master/src/index.html#L214

chrisui avatar Jan 11 '20 22:01 chrisui

Hi Chris, sorry I don't think I understand fully. What are the events you want to pass to other elements?

Do you mean using a custom event? For example: https://developer.mozilla.org/en-US/docs/Web/Guide/Events/Creating_and_triggering_events

Or do you mean that the overlay elements are blocking the events that should pass through to canvas underneath? In these cases, if the overlay is non-interactive, you can fix it by css pointer-events: none on the overlay.

williamngan avatar Jan 13 '20 01:01 williamngan

The latter. Sadly I can't use pointer-events because there are buttons in the overlay and ideally the text is selectable still.

Ideally you would be able to pass through two elements when initialising. First the canvas to render to and secondly, optionally otherwise default to canvas, an element to bind events to which would avoid these issues. Ie. here you would not always bind to the "canvas" but to the "event target element" (which would default to canvas)

I also reckon when you pass through a non-canvas element and Pts creates a canvas node for you, the events should be bound to the element I chose.

Given html

<div id="container"></div>

And initialised with

Pts.quickStart("#container", "rgb(22, 22, 22)");

I'd expect Pts to create canvas and construct the tree

<div id="container">
  <canvas>
</div>

And for events to be bound to div#container (the element I was explicit about).

Alternatively without changing this behaviour just add a new parameter for setting which element to bind to.

Pts.quickStart("#container", "rgb(22, 22, 22)", "#container"); // 3rd parameter is the event target

And finally another possibility would be to add a parameter to the bindMouse (etc) methods to accept an element to bind to.

space.bindMouse(true, '#container');

chrisui avatar Jan 15 '20 12:01 chrisui

Thanks @chrisui - let me take a look into this.

williamngan avatar Jan 18 '20 10:01 williamngan

One quick idea @chrisui -- if you hack it by extending the CanvasSpace class and hardcode your container div like this, I wonder if it would work?

class AnotherSpace extends CanvasSpace {

  bindCanvas(evt, callback) {
    document.querySelector("#containerID").addEventListener( evt, callback );
  }
  
  unbindCanvas(evt, callback) {
    document.querySelector("#containerID").removeEventListener( evt, callback );
  }
}

williamngan avatar Jan 18 '20 10:01 williamngan

This should work well enough for my use case, though worried that there may be other internals which get confused due to event element being different to that which the space has reference to. Ie. calculating absolute mouse position using scroll+element offset etc.

chrisui avatar Jan 26 '20 13:01 chrisui

Agreed. Will think about how to support this in the API.

williamngan avatar Feb 03 '20 01:02 williamngan