The task is to draw a curve ob canvas. The problem is that if mouse is moved too fast, the coordinates are skipped and not captured.
(Html5/Js canvas capturing mouse coords when it moves fast - my previous post..)
Is there a cross-browser way to limit mouse speed inside an element (div, canvas, etc.)?
I assume by "limiting mouse speed" you actually mean enable capturing high volume of mouse events so that you get more detailed information, or resolution, of the mouse path.
The browser will normally work at a high-level when it comes to mouse events. The system will capture the mouse events, but the browser will do many other tasks such as pushing events, bubbling them etc. and only capture the current mouse position when it actually can.
To compensate for this you need to use all sort of tricks such as splines.
Possible workaround
I don't intend to make a broad answer for this as it will quickly become out of scope to go through the steps and scenarios you would need for a spline approach (interpolation, knee-breaks which require relative angle tracking, smoothing etc.).
However, there is a new API called Pointer Lock API (see demo and source in that link as well) which allow the browser to work at a lower level closer to the system, so it can spawn mouse events faster and at a higher volume than it could otherwise.
It do have some drawbacks as with all low-level approaches:
You need to render your own cursor
Mouse movements are not limited to the edges so you need to provide wrapping or limits yourselves
It will request user for permission
Not supported in all browsers
And it target games and 3D more than drawing application
But this is the closest you will get to high volume of mouse events without interpolation etc.
Related
I am using javascript/jquery/jquerymobile/cordova in my application currently testing on Android.
I am trying to detect the movement of a touch in a screen into the multiple targets/buttons that there maybe in the screen.
In a desktop hoover: would just do what I want. However, it does not work in mobile platforms as it does in desktops.
In my problem I am looking to throw some 288 very small buttons and I want to receive an event for each target that is touched/mouseover along the journey of the finger in the screen ( 1 single touchstart-touchmove-touchend). As I understand it as soon as a touchstart happens, that target is the only one receiving the event notification, no matter where the touch ends or what else is touched.
I could do it with canvas and calculate the distance to 288 points at each finger movement etc. But would be resource intensive, specifically for a task that a web browser excels. Hence I am looking to see how much can I delegate to the browser.
-- edited
I found a possible answer in How to find out the actual event.target of touchmove javascript event
I will be testing today. However, I am concerned by Steven Lu comments on performance. Specially as in my case there is a significant number of object/points that I need to track.
I'm trying to explore how feasible it is to create an HTML5 interaction where a touch can be conditionally captured by the initial direction of the motion.
The goal is to capture and track the motion of the touch only if it initially moves in a horizontal direction. Combined with a responsive page layout which only scrolls vertically, we should be able to use horizontal swipe motion to do something cool by tracking it.
The problem is in the seeming impossibility (especially on iOS) of performing touch sequence capture conditionally.
In order to track a touch (and by this I mean specifically obtaining the stream of x,y coordinates which represent the position of the finger over time), touchstart has to be preventDefaulted in order to prevent the page from engaging native momentum-scroll. Native momentum-scroll, while in operation, suspends all JS execution (setTimeout, rAF, jQuery animate et al...) and even CSS keyframe/animation/transition execution.
I would really like to know if there's a way to somehow condition the preventDefault() of the original touchstart event. It's completely possible for JS to store that event object, and then not call it until some later time (when it is determined that we are indeed interested in preventing the native scroll from starting).
But this is certain to fail because the default behavior of not running preventDefault() on that event is to engage native-scroll, which then will block JS execution for the entire remaining duration of the scroll. Failing to return the event listener function attached to touchstart does not appear to be an option. It would freeze everything.
The tentative answer, then, without any additional insight, is that all swipes must be captured if we want to be able to capture it at all, and scrolling has to be "faked" via external means à la (iScroll)[http://cubiq.org/iscroll-5-ready-for-beta-test] (personally I would want to explore some sort kind of combination of rAF and window.scrollTo and would be surprised if iScroll 5 does not employ these APIs)
Incidentally the description for the 4th demo there got me really excited, but it turns out that all it does is create a page section that iScrolls horizontally while the rest of the page behaves regularly, which is entirely mundane.
I am trying to develop a "Web App" (for lack of better terminology) that displays a sort of interactive map using the HTML5 Canvas element for mobile devices. The map has about 30 buildings (made from semi-transparent PNG images on it) of different shapes and sizes. I want the user to be able to tap on any of the buildings to get information about them. The buildings are often within the same theoretical bounding box of others, so it isn't as simple as just detecting when the user taps in a bounding box (imagine a U shaped building with another building inside the U). Therefore, it should use some sort of raster pixel detection. To make matters more complicated, I need to allow the user to zoom in/out and pan around on the map (because 30 buildings and a map are way too much to show a user on a tiny cellphone screen). So scaling and moving smoothly is a necessity.
I am looking for a JavaScript library that can support these functions:
Image pixel detection
Mobile touch events
Canvas (or stage?) scaling
Usable on mobile devices
So far, I have found KineticJS which supports all of these features. But when I try to move the map with more than 4 buildings on the stage, it is way too jumpy. I tried checking into Fabric.js but it doesn't seem to have pixel detection (as it selects the image when you click within the bounding box, not the actual image itself).
Is there any other JavaScript library out there that can do these things?
Thanks for any help!
The KineticJS is pretty good ( the best lib i found so far )
I never tried to use png images with it, but zooming and panning with a few hundreds primitive objects is pretty smooth (without pixel detection - I imagine the pixel detection is quite cpu expensive operation ).
Maybe you could try overlay standard polygons ( a few for one building ) and attach to the same click/tap event.
Also you don't necessary need to move objects on the canvas you can just put bigger canvas in smaller div ( with overflow:hidden) and drag the whole canvas element.
I'm developing a web game application with a, HTML5 canvas that has to react to "click" events (in the general meaning).
On a mobile platform (or touch-capable), that means reacting to onTouchDown, on a desktop/laptop platform (with a mouse or pad), that means reacting to onMouseDown.
Problem is, if I handle both events, then sometimes the same "click" will result in both events getting fired, so I get a double signaling.
What would be the best way to handle that?
Currently, upon the first touch event I receive, I turn off mouse events, but that may be a bit heavy handed if the platform supports both touch & mouse clicks (f.i. an Android tablet with attached keyboard/pad/mouse)
Measuring the delay between touch & click to ignore a click after a touch doesn't work too well, as there are circumstances where user may touch/click at a high frequency, so a too long delay leads to dropped double taps/clicks, and a too short delay lets through the occasional double signaling slipping through.
I've looked at user-agent detection, but that seems quite fragile (many user agents out there), and doesn't solve the cases where the platform has both touch & mouse/pad.
Maybe a combination of your suggestion:
Measuring the delay between touch & click to ignore a click after a touch doesn't work too well, as there are circumstances where user may touch/click at a high frequency, so a too long delay leads to dropped double taps/clicks, and a too short delay lets through the occasional double signaling slipping through
And detecting the x,y coordinates of the tap would decrease the false positives. So if both events (tap & click) happening in sequence got the same coordinates they are handled as the same.
Or maybe let the user switch (through some sort of options screen) if he wants to use mouse or touch for his device if both is supported. Display a warning message for example saying you're on a touch device so we enabled touch events, if you're using a mouse please see options or something like that.
Most users would be happy with the auto-choice and everybody unhappy can change it.
The idea: I'm creating a simple WebGL script (using mrdoob's wonderful three.js) that allows the user to control a camera in a world of objects. The camera is supposed to simulate traditional first person shooter cameras (reference Team Fortress 2, for example). That is, the camera moves only when the mouse moves.
The issue: in Javascript, the only way to detect mouse movement is if the cursor itself moves. By comparison, FPS games don't show the cursor -- they only base the movement of the camera off of how the mouse itself moves. So, you can move your mouse all over the mousepad in any direction and it always works.
On a browser though, since camera movement is based on the cursor, you can't move but so far. When the cursor hits the edge of the screen, the user is unable to look any further in that direction (e.g. you move your mouse to the left edge of the screen, you can't look left any more).
The solution: I've thought of two solutions, but neither of which I know how to implement. Either
After the mouse is moved, the javascript resets it to the center of the screen. That way, after every mouse movement the player is free to again move in any direction. The issue with this is that, based on the research I've done, Javascript is unable to control the position of the user's mouse (understandably, as it would be an incomparable nuisance on malignant sites).
Or, the mouse "wraps" around the screen. Meaning, when the user reaches one edge of the screen, the mouse would simply continue on to the other side of the screen. (see: http://www.digicowsoftware.com/detail?_app=Wraparound) However, it appears that this too is not an inherent capability of javascript, but instead is only something a third party program could solve.
So, does the problem make sense? If so, is there any way I can implement the above solutions, or is there another one I'm missing?
For anybody that still interested in achieving this, it is now somewhat available.
Using:
document.addEventListener('pointerlockchange', changeCallback, false);
see example http://www.html5rocks.com/en/tutorials/pointerlock/intro/
The worldwide community is currently working on a draft spec to solve this issue. What you're stating is called "mouse-locking". I've worked a little on the first phase of this standard to help lay out what's needed. Please, vote for these issues and subscribe to the indicated mail lists in order for all of us to get this issue corrected ASAP.
Chromium Bug: http://code.google.com/p/chromium/issues/detail?id=72754
Firefox Bug: https://bugzilla.mozilla.org/show_bug.cgi?id=633602
W3C Mail list: http://www.w3.org/Bugs/Public/show_bug.cgi?id=9557
Draft proposal: https://docs.google.com/document/d/1uV4uDVIe9-8XdVndW8nNGWBfqn9ieeop-5TRfScOG_o/edit?hl=es&authkey=CM-dw7QG
However, there's still a way you can achieve your objective (which is the other way i found): A native plugin that takes control of the mouse.
(I'm making a game too which is a FPS but currently won't be released due to this limitation)
You're right about all of this. Standards-based web tech isn't going to give you mouse capturing like you want.
That said: you might be able to craft (or find) a special SWF that can collect mouse movement data and pass that to javascript. It won't constrain cursor movement, although you can use CSS to conceal the cursor while mouse capturing is active. But it might be able to e.g. continue firing "move mouse left" events even when the cursor has reached the left edge of the screen.
Any such SWF will probably fail to capture movement when the cursor is outside the viewport i.e. over the browser chrome.
Given that it's apparently not possible to do this as such in HTML5/Javascript, what about this variant: treat the mouse position (not mouse movement) as representing the rate of turning.
So if the mouse is more than a certain threshold left of the center, the camera turns left; the farther left the mouse is, the faster the camera turns. To stop turning, the player moves the mouse back toward the center.
To me this is an annoying UI, at least initially, but maybe the player would get used to it. Since we don't have any perfect solutions, it may be worth trying. You can mitigate the problem by allowing the arrow keys to work the way they do in many FPSes, rotating the camera when they are pressed down.