I have my object tracking the mouse using the onmousemove event. But I would like to make it smooth. I'm sure this can't be difficult in jQuery but I'm not finding any really good resources.
One idea I had was to simply use the animate function and calculating the offsets that I want to move to. Then if the mouse moves again before the animation is complete, I would use the stop function to stop the animation. I would recalculate my destination and away I go again. This seems a little hack-ish and I also imagine that it will be a little jerky. I'm sure there has to be a better way. Any Ideas?
EDIT
Sorry I didn't make my problem very clear. I have the object tracking the mouse in real time, so that it moves exactly the same as my mouse. The problem is that I want it to be smooth and lag behind with acceleration effects like Andy Lin mentioned below. I'm just a little lost how to actually implement this.
I am afraid, that there is no better way, than animate. If you add a smoothing function, then you would simply do the same thing that animate does. Be sure, not to queue your animations or they will look weird. I got nice results with this:
var obj = $('<div style="width:50px;height:50px;background:red;position:absolute"></div>');
obj.appendTo(document.body);
$(document).bind('mousemove',function(ev){
obj.animate({top:ev.pageY,left:ev.pageX},{queue:false,duration:200,easing:'linear'})});
when you are using onmousemove, you do not need to have the object change its behavior with every invocation.
e.g. you can add a timer to say that within period of time, the object will not response to mousemove and will follow its original path, and upon timeout or mouse move stop, move according to the destination.
also, you can simulate an acceleration and slow down effect with animation settings.
Related
In Adobe Animate CC HTML5 Canvas (createJS), I'm trying to do something very simple, to trigger an animated rollover when the entire stage of an ad is moused over, and to trigger an animated rollout when the mouse leaves the stage. It should be very simple, but it's not. Using mouseenter and mouseleave on the stage is laggy and only works intermittently. It's the same with mouseover and mouseout.
Here's the code that's laggy and intermittent:
stage.addEventListener("mouseenter", fl_MouseOverHandler.bind(this));
stage.addEventListener("mouseleave", fl_MouseOutHandler.bind(this));
function fl_MouseOverHandler(){
this.btnOverAnim.gotoAndPlay("on");
}
function fl_MouseOutHandler(){
this.btnOverAnim.gotoAndPlay("off");
}
I also tried mouseover and mouseout on a button the entire size of the stage and I got the same issue. (Also doing it this way doesn't work at all from inside a frame, and the ad is served inside a frame). I put the var frequency way up to 90 to see if that would help with the lagging, it didn't.
This was the simple mouseover / mouseout code I tried:
var frequency = 90;
stage.enableMouseOver(frequency);
this.bgCta.addEventListener("mouseover", fl_MouseOverHandler.bind(this));
this.bgCta.addEventListener("mouseout", fl_MouseOutHandler.bind(this));
On the createJS website it says "You can monitor whether the pointer is over the canvas by using stage.mouseInBounds AND the mouseleave / mouseenter events." So I'm wondering if using stage.mouseInBounds will help (but I can't find an example anywhere of how to use it). But I actually don't think it'll help because I think this whole problem is about createJS not reading where the mouse is fast enough.
Does anyone know how to fix this lagginess and intermittent firing? A work around? Why does createJS not just monitor the mouse events constantly like pure js?
Also mouseenter and mouseleave on the stage in createJS do not work on tablets or mobile and that's a problem, so it would be better to do this with mouseover and mouseout on a button the entire size of the stage. I did try using mouseover and mouseout and having 3 pixels space around the button between the edge of the button and the edge of the ad banner, this helped, but it was still firing intermittently.
Your thoughts and ideas please.
Mouseover checks are expensive. A canvas is essentially just a bitmap, so EaselJS can't use mouse events from the browser (you just get one for the entire canvas). Instead, mouseover in EaselJS requires every element to be drawn to a 1x1 pixel canvas, and then checked for fill. This gives pixel-perfect detection, but is costly if you are either checking a lot of content, or checking too often.
Reduce your frequency:
It looks like you have set the frequency to 90. This is really high (11 ms between checks, which is basically trying to achieve 90 fps). The default is 10, which is slower than a good framerate, but fast enough to feel responsive. You can probably bring it down to 20 or so to give you a peppy check without it being unnecessarily high.
Modify interactivity: Another thing you can do is filter out exactly what gets checked. By default, all display objects get checked -- but you can reduce this by turning off mouseEnabled on anything you don't care about (omitting them from the check), and turning off mouseChildren on containers that you want to treat as a single object (so something like a complex button is drawn once, instead of all its contents being drawn individually).
// Example
myBackground.mouseEnabled = false;
myButton.mouseChildren = false;
Hope that helps!
Friends, I know this was asked 4 years ago, but the lagginess in Adobe Animate CC V.21 is no different (horrible) regarding mouseenter, mouseleave, mouseover and mouseout. After 10 times of rolling over/out the page becomes unresponsive. I was able to alleviate this using stage.mouseInBounds on a setInterval. The original poster could not find an example, so here is what I did:
// Place this in a keyframe on the timeline where the named cta exists.
setInterval(function(scope){
if(stage.mouseInBounds){
createjs.Tween.get(scope.cta).to({scaleX:1.1, scaleY:1.1}, 150);
}
else{
createjs.Tween.get(scope.cta).to({scaleX:1, scaleY:1}, 150);
}
}, 150, this );
Make sure to pass this into the end of the setInterval function as an argument for the callback function as to not lose scope. I am guessing this can be reworked to use gotoAndPlay() on the timeline, in this instance the built-in tweener for CreateJS sufficed for what I needed.
I have a container that is quite similar to an image slider, and designed for horizontal touch/mouse drag to move between slides. For aesthetics, an easing function is applied so that it glides into place centered on each slide when released. The method of movement is "transform: translateX()".
The problem I'm currently having is that, if the user releases, then touches and and moves it again while it's already in motion, it will jump to the slide at the end of it's transition. So for example: if you are in slide 1, move it and release while it's in the zone for slide 2, and then try to move again while it' still in motion, it will jump to slide 2 immediately, and then move from there to wherever I move my finger.
What I'm essentially looking for is a way to get the intermediate transition distance while the translation animation is running. Is there any way to measure where an element actually is in the middle of transition? If not, what are some solutions for this situation?
EDIT:
I found out the root cause to my issue, although it doesn't change the focus of the question. To give a broader explanation of what was going on, I'll include it here.
The default transition duration time was set to 300ms. When a user drags on the content by mouse or by touch, this was set to 0ms so that it wouldn't lag behind the user's movements. When released, it would be set back to 300ms. If it was grabbed again while it was in motion, it would take the position it was transitioning to and snap there when the duration was set to 0ms. This was better than then alternative of allowing it to continue to flow there while dragging again, as the content would slide under the drag point.
Per the comments on the question post, I assume this means the answer to my first question is: no, you cannot get the intermediate values directly during translation.
As to the second question, the comments mention the option of preventing activity until the animation completes. While this would work, I felt it would also diminish the UX, and so I decided to try something a little different. My solution seems to work quite well as a workaround, and so I decided to answer my own question and post it here for others. I also edited the question with a little more detail.
What I ended up doing was using a timer to predict the position of the intermediate value, so that if interrupted, it would appear to seamlessly stop mid-transition in the correct place.
Doing this required a little math, and the precise formula is dependent on what sort of easing is employed. "Linear" easing is the easiest to predict, but the others are quite doable with a little bit of trigonometry. I used "ease-out", so I'll include my solution for that one in pseudo-code below:
startX + (finishX - startX) * sin((now - startTime) / transitionDuration * PI / 2)
startX is the position the slider was at when released (beginning of transition).
finishX is the position the slider is moving towards (end of transition).
now is the current time in milliseconds.
startTime is the time the slider was at when released (beginning of transition).
transitionDuration is the amount of time the transition takes to complete in milliseconds.
In summary, the above allows you to predict the position of an element during transition. While specifically written for "ease-out", it should be trivial to adapt it to other basic curves.
I'm creating a custom scrolling control using HTML's Canvas that behaves a little like a spreadsheet grid. I have most standard cursor control behaviors set up, including using the mouse or arrow keys to extend the selection.
What I'd like to do next is allow the user to extend the selection by clicking and dragging off the canvas. I don't need help with the actual code, but I'd like to know if anyone has programmed something like this before, and if so, how did they approach it? Here are the ways I can think of:
Track the mouse's general direction while over the control, and on mouseLeave+mouseDown set up a timer to scroll that direction until mouseEnter+mouseDown
Determine the last location of the mouse before mouseLeave+mouseDown and use that to determine scroll direction
Start a slow scroll when mouse is within a few pixels of an edge (which edge determines direction) and then scroll faster on mouseLeave+mouseDown
Somehow involve window.mouseMove (instead of canvas.mouseMove) and track it that way (which seems really ugly to me)
Something else I'm missing that will seem really obvious in retrospect
I can handle the code, I just want to figure out the best conceptual approach to take. Ideally, I'd love to handle extending the selection diagonally (scrolling right and down simultaneously, or at least alternating between the two so it appears that way), but that's not a deal breaker.
You can use .setCapture to let your canvas continue to get mouse events even when the mouse is moved outside the canvas:
https://developer.mozilla.org/en-US/docs/Web/API/Element.setCapture
For example, when using jquery ui draggable (http://jqueryui.com/draggable/) the object follows the mouse rather than moving with the mouse. It seems like there is a one frame difference in position.
Why is that? Is there a way to get around this?
The animation is chasing your mouse's movement because it has to wait for the mousemove event.
And, while the event fires fairly rapidly as you move the mouse pointer, it still fires after the pointer has actually moved. So, the box' position is always being updated to where the pointer was if it's still in motion.
The event will also be throttled by the (mostly) single-threading of JavaScript. If the engine is busy, including with a previous trigger of the event, the most recent trigger will have to wait for the engine to again become idle.
And, counting those triggers as frames, jQuery also employs easing so the box' position doesn't jump around oddly when there are irregularly-spaced frames.
You could try to build a more efficient function, but it more or less depends on the browser, and system. If your browser and/or your system is slow, then you will experience a lag while dragging or following the mouse.
I experienced no lag with the link you provided.
I am trying to make an animation using javascript.
Basically, there will be a window on a wall, and when the mouse hovers over, the window will open up, and an image will show.
I know this is really specific, but can someone good at javascript help me with it?
My thought on it is to create a gif that does the opening animation, and use javascript to control the timing.
What do you think?
Make a div and position it absolute so that this div will represent your window. Then make a function that represent an animation. Each time when it is called the function should make a tiny change to position and size of "window". Call this function at regular intervals with setTimeout and you will achieve animation. If mouse goes out you have to start rollback animation. Read a little bit more about JS times and u will write it.
Also as advice always white times like this:
setTimeout(func() {
....
}, 1000);
In this case func() will be called after 1000ms. So you can add this timer at the end of your function. Make your function to be called from func() and you will have the loop.
Hope this help you
I do not know if this will help but I created a website with a similar function for opening doors with the mouse hover. The website is http://www.bandofamericasfew.com/ Go view the source and see if it helps. If you have any questions then let me know.