Canvas mouse events with requestanimationframe - javascript

I'm working on a game with the goal to use all canvas.
Currently I have a mouse event for my buttons (mousemove, mousedown, mouseup). Should I just update my canvas-buttons directly from this event or integrate it with requestionanimationframe? I read that a mouse event can be called hundreds of times per second...
Maybe extraneous to the problem: When triggered the event calls objects with buttons to check for mouse position (this is due to only the top-most layer registering mouse events and the way pre-rendering works). Essentially, it's not a 'real' mouse event on each canvas object/button.
Thanks!

It's hard to answer your question without knowing more about your game, but in general:
If your game critically relies on the timing of button presses, then run your game logic with each mousedown (don't wait for rAF). For example, in a shooting game the enemy might move off-target if you wait until rAF to test if the bullet hits the enemy.
If your game relies on the quantity of button presses regardless of the time, then just accumulate the mousedown count until rAF. For example, in a fast-twitch game you're just testing how many times the user can press your button in response to a prompt.
Either way, put your display redraws inside rAF to make the game display as efficiently as possible.

Related

Enabling ongoing d3 node animation triggered by mousedown/drag

I'm trying to create a node animation that's triggered on an event like mousedown or drag, but doesn't die when the existing mousedown/drag event ends.
For example, when the user is dragging a node I want the node stroke-width to transition back and forth between 2 values. So on my ondrag event I call a function that triggers the animation - which works great after 1 drag event if I keep the mouse where it is, but is immediately reset after the second, third drag etc.
I suppose what I'm asking is more of a javascript question, but does anyone know if there's any way that I can say "while (drag/mousedown)" instead of having to trigger a new call every time (and in the process destroy the reference to the old active call that was handling the animation).
Even with mousedown I have the same problem - i.e. the animation works great on click/hold, but then when you move the mouse, you get a mousemove event which destroys the reference to the running animation function.
Thanks for any thoughts!

Mouseover and mouseout events won't trigger when mouse moves too fast?

I wrote a live demo to show this problem:
http://cssdeck.com/labs/wcczap11
If you move mouse fast between the blue, red and green areas, you will see red 'y' logs are not appear between x and z logs, which means you can't get the red area mouse events.
This is what I want:
But when mouse moves too fast:
I just want to know is there a way that no matter how fast I move the mouse the result will always be the same with the first image?
I'm not completely certain if it affects javascript, but different mice have different polling rates (measured in Hz) and if your mouse is 1000hz and you move 1000px at a constant velocity you should pick up every pixel.
However in reality we move the mouse very fast to begin and slow down as we approach a target to improve accuracy. meaning the first 700ish pixels will have been moved faster than the 700hz could poll and so you're missing values where the mouse moved more than 1px in 1hz.
That's kinda of a dumbed down version (mainly because I don't know everything about it) but basically small-hit-targets are prone to being missed by mousing events.
You could attempt to make target-areas larger, but it still won't fix everything :)
The problem here is a simple one.
The events aren't being "lost" as such. They are never actually triggering in the first place: due to the speed of transit, at no point is the browser picking up the pointer as being "over". If that's the case, then it can't trigger "out" either, as it was never viewed as being "in" in the first place.
It doesn't get lost. It comes and goes but you cant see because you move the mouse too fast. And in your example it is not lost.
Calling a callback that takes too long to execute can cause the browser to skip a poll until the next polling tick (Have you ever seen the [Violation] 'message' handler took 326ms console messages?). You're using jQuery to attach the event handlers (and I don't know much about jQuery), so there's a chance that the event handlers aren't passive.

Enable mouseup / mousedown but prevent click behavior

I have a data visualization here (the second one):
http://mikeheavers.com/main/work
If you click on the circles representing skill fields, it reveals inner green circles with the particular skills. If you hold down on the green circles representing the skills, they animate, grow, and then shrink back on mouse release. However, if you simply click on the circles, they grow, but do not return to their previous size (the mousedown is not registered I guess) - which results in a circle that will constantly get bigger each time it is clicked.
Is there a way to prevent click behaviour, either through d3 or through Javascript / jQuery? I only want mouseup and mousedown.
I'm observing different behavior than what you described.
If you single click a circle, it doesn't matter how long the click is (whether it's held or not), it returns back to its original size.
If you click a circle repeatedly and quickly, this is when it starts to grow and does not return to its original size.
If you hold down a circle and then move your mouse outside of it, it both stays pink and doesn't return to its original size.
I think attaching a simple .on('mouseout', handler) to return spheres to their original size will solve the last issue, which is pretty glaring, and any missed mouseup events due to moving outside. You can also attach a mouseup to the whole document (d3.select('body').on('mouseup', handler)), which will catch any such event; then you would just need to record the last sphere that was clicked.
Additionally, to fix your original problem, you can make sure that mouseup events are triggered by adding e.preventDefault() in the mousedown events. This will prevent fast clicks from turning into double-clicks or other events by the browser.
Other posts that discuss these issues:
mouseup event isn't always triggered
mouseUp event on drag

vmousemove is triggered even when no move has been performed

On iPad the vmousemove event is triggered even when no move has been performed. Why's that?
Steps to reproduce:
Open http://jsfiddle.net/dcbV7/
Tap A div then B. Only tap them, but fast
Result: you see vmousemove event is triggered
vmousemove simulates the movement of a mouse. It would be as if you clicked A div, moved the mouse to B, then clicked it. There would be no other way to get a mouse from one to the other, after all.
If you try this on a device with a mouse, you'll notice that vmousemove is triggered every time the mouse is actually moved. The best heuristic they have for mouse-less environments is that touching two points close together in a short amount of time is similar to doing the same with a mouse.

mouseover fired with mouse still and element moving

I am in a situation where I need jQuery's mouseover event to be fired when an element (in this case an image) moves under the mouse, so unlike the common situation is an element that is moving, not the mouse.
Do you know of any library/gist/technology that could help me in this sense?
I've tried with flash but with no luck, is this something than can actually be done?
You can track mouse position by binding a handler to mousemove on the body, and calculate after every move of the image whether the pointer is over it.
I ran across a similar issue. In my case I did a "good enough" workaround by keeping track of the time the mouse last moved and then in the mouseover handler seeing if the mouse had moved recently -- within 30ms of the current time. That way I can bail out in cases where the mouse didn't actually move, but I don't have to test the hitboxes myself -- something very hard to do right and fast, and fortunately something I can leave to the browser by doing this.

Categories