Balancing performance heavy procedures with real-time mouse input
To put this question succinctly, is there any way to offer a real-time web application that requires processing to be done at every coordinate 开发者_JAVA百科that a user moves their mouse to without dropping any mouse events?
With JS, if we want to keep track of the user's mouse location, we're essentially limited to attaching a mousemove
handler to some element. Unfortunately, if we're using the mouse location to perform some expensive procedures such as drawing dynamic graphics to the screen via WebGL or a 2D canvas, we can (and typically do) lose a lot of accuracy.
For instance, if we link the user's mouse to a camera in a first-person WebGL game and the user is moving around erratically, some of the immersion will be lost as the camera fails to accurately mimic where the mouse is pointed. Or, even more simply, if we want to stamp multiple images onto a 2D canvas wherever the user drags the cursor, chances are we won't be able to produce a nice smooth curve if the user happens to draw one.
Ultimately, since JS is single-threaded we can't just have a separate thread running with the sole purpose of collecting mouse coordinates and let the application process the input as fast as it can (maybe a web worker would help here?). Similarly, we can't very easily prioritize collecting mouse events over the processing that needs to happen, because we can quickly start starving the processing side of things.
Is there some sort of approach that I'm overlooking here? If all an app does is record mouse coordinates, you typically get a very accurate record of where the mouse has been. The problem arises when we have to do some significant, but not unreasonable, processing based on that input in real-time.
Depending on what you're doing, you may be able to interleave your processing with event handling by working a little at a time in a timeout handler. This gives the event handlers a chance to fire in between.
var workInterval = 0; // or try other small values
function doABitOfWork() {
// ... Do stuff, but don't take too long ...
if (!finished) {
setTimeout(doABitOfWork, workInterval);
}
}
setTimeout(doABitOfWork, workInterval);
I've used this trick successfully to make the page responsive while constructing a heavy HTML table.
精彩评论