CindyJS / CindyJS

A JavaScript framework for interactive (mathematical) content.
https://cindyjs.org/
Apache License 2.0
658 stars 52 forks source link

Points keep sticking to the cursor when released outside the browser window #813

Open porst17 opened 5 years ago

porst17 commented 5 years ago

Click on a geometric object, e.g. a point, and drag it. While still pressing the mouse button, leave the browser window and release the button. When re-entering the canvas, the point still sticks to the mouse position despite the mouse button not being pressed anymore.

The bug also appears in the demos at https://cindyjs.org/.

strobelm commented 5 years ago

Hi, thanks for reporting. The reason for the behaviour is that we bind the mouseup event to the canvas and not to the the browser window. This could be easily changed, but I'm not sure of this has implications for multitouch. @montaga could you comment on that?

kortenkamp commented 5 years ago

If this is bound to the browser window we also might run into problems when several instances are on the same page. Maybe it is a good idea to follow mouse leave/enter events (don't know whether these exist in JS, only know that we used them in the Java version)

montaga commented 5 years ago

I am against binding the CindyJS-mouseup pipeline as it is to the browser, because this could unpredictably interfere with other applets and parts of the website. We are currently using e.preventDefault() for all events associated with CindyJS. Moreover, the problem would remain if the mouse leaves the entire browser window. (https://stackoverflow.com/a/49167020)

mouseleave and mouseenter events do exist in JS. Should we trigger the classical mouseup and mousedown pipeline whenever the mouse is pressed and mouseleave and mouseenter events are fired on the canvas? With this, we could maintain the paradigma that the mousedown and mouseup script is always evaluated in this order. With this, no points could be moved far outside of the visible construction. However, this behavior is different from Cinderella, where the drag can continue outside of the window.

Surprisingly, the (multi)touch events are currently handled in CindyJS nicely: A touchend event is also fired if the touch, which started inside the canvas, ends outside the canvas. Compare examples/multitouch.html.

A clean solution in an ideal world™ could be to avoid mouse-events and refactor everything to PointerEvents. Then we could use setPointerCapture to track the PointerEvents until they are released (even if outside the canvas). Unfortunately PointerEvents are not yet entirely supported on Safari on iOS. In particular, setPointerCapture does not work on Safari yet :(

kortenkamp commented 5 years ago

I always disliked that the mouse cannot move points when I drag them outside the window. And there are several situations where it makes sense to be able to do that.

So, if it is possible to capture mouse events until the mouse button is released, this would be the preferred way to handle it. Still, it is necessary to watch out for undesirable side effects.