How can I create a smooth animation that eases in toward a target as it changes position?
As this jsFiddle shows, the animation stops or gets blocked during moveTarget() instead of continuing toward the new target coordinates.
What would be the ideal implementation / structure to achieve the desired effect?
Ok, answering my own question here in case anyone else has this problem.
Instead of calculating change (change = finish - begin) each time moveTarget() fires, it is constantly being calculated in onEnterFrame(). So moveTarget() only responsible for getting the new X and Y positions.
This allows the values to ease toward the target.
I also permanently set the time value of the easing function to always be 1:
easeIn(1, begin, change, duration);
The example answer is in this revision jsFiddle: http://jsfiddle.net/dannygarcia/LqP2R/45/
Related
Hello my current JavaScript is this, to scroll the page to an id tag further down my website page:
function scroll(element){
var ele = document.getElementById(element);
window.scrollTo(ele.offsetLeft,ele.offsetTop);
window.scrollBy(0, -100);
}
How can I make the function scroll smoothly ?
First of all, this is not Java, this is JavaScript, and those two are different, they are not just two names for one programming language...
For your problem, I would do something like getting the current position of the scroll by using document.documentElement.scrollTop (but this one returns 0 on chrome) and the wanted position of the scroll by getting your element's coordinates, and then just move the scroll for a bit of the distance every frame by using window.scrollBy() method.
However, I would not suggest this method, because there are other, better solution would be to use this
Is it possible to translate an element by a constant amount with CSS? For instance, we want to move a div in 50 pixel increments up the screen. Right now, we use update the translate value manually, but this creates a choppy effect.
Here's the code, where translate equals a value that increments by 50 every time this line is called:
$(element).css( '-webkit-transform', 'translate3d( 0, ' + translate + 'px, 0)' );
We need this work on mobile devices so we can't use jQuery animate because it is not smooth enough (in our experience) on mobile. We need to translate by a constant amount because we need to track the element's position so we call the translate code every X ms.
Instead of constantly firing off repeated animations I'd just set one animation with appropriate values, then detect the current position in your loop rather than trying to do the animation in it. This updated example from the linked question seems to indicate it would work.
You may want to interrogate the transform property to get the current translation values if they're going to be more complex than simple top/left. You should get a value that looks something like this:
matrix(1, 0, 0, 1, 0, 300)
There are several jQuery plugins that extend the animate method to use CSS3 and make animations very smooth on mobile devices.
I've used in the past a couple of plugins, don't remember the ones I used, but a quick Google search gave me this one:
http://ricostacruz.com/jquery.transit/
It would be something like this:
$(element).transition({ y: '+=50' });
I would like to do something like this in HTML5 where I have something like:
I want to be able to make it so that when I click on the Start button, the tickmark gradually moves to the next tick and increments by 1 per second, clicking on stop stops the behavior, and clicking on start again resumes from the current spot. The box at the top just shows the number of seconds corresponding to the red tracker bar. Assuming the user can specify the number of tickmarks (i.e. could be 20 seconds/tickmarks wide ro 10 seconds/tickmarks wide).
I have seen the JQuery UI Slider http://jqueryui.com/demos/slider/ though it has no tickmarks and am unsure if it really is the best way to go about doing what I described or if there is some better way.
What is the best javascript, jquery, html approach of doing this?
Try this - I felt like doing an exercise!
http://jsfiddle.net/zBKJk/
Only quirk is that the ticks along the bottom don't align exactly with different values of TICKS_ON_BAR. Probably a minor CSS/math issue.
You can change these variables
var TICKS_ON_BAR = 10; // Number of seconds to show on the bar
var TICK_RATE_MS = 100; // Interval to tick at (in milliseconds)
Also added a handy callback function
function timerComplete(){
// Do something further when the timer hits the end of the bar
}
Edit: If you want this to run smoothly, you could make the interval lower or (since you specified HTML5) use a linear CSS3 transition to make the changes animate:
http://jsfiddle.net/zBKJk/1/ (a bit glitchy, I just dumped in the example css from w3schools)
Animating this as is with jQuery is glitchy also: http://jsfiddle.net/zBKJk/2/
i am using ImpactJS to create a game on HTML5 and JS, when a animation is running, is it possble at any frame to reverse the animation frame flow (not flipping) ? I used rewind(), it only gets back to the first frame, is there any reverse()?
If you don't mind being a bit hacky something like this should, in theory, work:
animation.sequence = animation.sequence.reverse(); //Reverse the animation
animation.gotoFrame(animation.length - animation.frame - 1); //Set the frame to be the same frame as it was before.
Basically the sequence property of the ig.Animation() class is what determines the order the frames are run, the update just iterates over them based on a timer. Reverse that and you reverse the animation. You can just use the same code again when you want to reset the animation to be forward.
You may need to also do animation.rewind() instead of gotoFrame() if you want the full reversed animation to play out.
Otherwise you could use 2 animations and use gotoFrame() when switching animations to start the correct frame. Also of note the code above will duplicate one frame of animation, you'd want to remove the -1 (looking at the source I think this will be okay in the case where frame = 0).
No, but you could easily write your own using the plugin system.
Or just create a new animation starting with the enetity.currentAnim.frame and then working backwards through entity.sequence.Then setting the current animation to the new one.
No there isn't reverse that i knew of
but instead you could just create new animation that has reversed sequence
then switch to that animation wherever needed
The problem I'm trying to solve is "What's at this position?"
It's fairly trivial to get the x/y position (offset) of a DIV, but what about the reverse? How do I get the id of a DIV (or any element) given an x/y position?
Unfortunately, triggering a manufactured/simulated mouse event won't work, since when you dispatch it, you have to provide a target element. Since that element is the one you're trying to figure out, all you could do is dispatch it on the body, as if it had already bubbled.
You really are left to do it on your own, that is manually walk through the elements you're interested in, and compare their position/size/zIndex to your x/y point and see if they overlap. Except in IE and more recently FF3, where you can use
var el = document.elementFromPoint(x, y);
See
http://developer.mozilla.org/En/DOM:document.elementFromPoint
http://msdn.microsoft.com/en-us/library/ms536417(VS.85).aspx
function getDivByXY(x,y) {
var alldivs = document.getElementsByTagName('div');
for(var d = 0; d < alldivs.length; d++) {
if((alldivs[d].offsetLeft == x) && (alldivs[d].offsetTop == y)) {
return alldivs[d];
}
}
return false;
}
Use a JQuery selector to filter the list of all DIVs for one that matches your position criteria?
Create a mouse event listener, then trigger a mouse event at that location. This should give you the entire stack of elements at that location.
Or, look at the source of Firebug.
If all you have is the X and Y position, (and you can't track mouse movement like you mentioned) then you will have to traverse the DOM, looping through every DIV. For each DIV you will need to compare its X and Y coordinates against those you have. This is an expensive operation, but it is the only way. I suggest you might be better off rethinking your problem instead of coming up with a solution for it.
One option is to build an array of "div-dimension" objects. (Not to be confused with the divs themselves... IE7 perf is frustrating when you read dimensions off of object.)
These objects consist of a pointer to the div, their dimensions (four points... say top, left, bottom, and right), and possibly a dirty bit. (Dirty bit is only really needed if the sizes change.
You could then iterate through the array and check dimensions. It requires O(n) to do that on each mouse move. You might be able to do slightly better with a binary search style approach... maybe.
If you do a binary search style approach, one way is to store 4 arrays. Each with a single point of the dimension, and then binary search on all four. O(4logn) = O(logn).
I'm not saying I recommend any of these, but they MIGHT work.
I think what John is saying is that you can use document.createEvent() to simulate a mousemove at the location you want. If you capture that event, by adding an eventlistener to the body, you can look at the event.target and see what element was at that position. I'm unsure as to what degree IE supports this method, maybe someone else knows?
http://developer.mozilla.org/en/DOM/document.createEvent
Update:
Here's a jquery plugin that simulates events:
http://jquery-ui.googlecode.com/svn/trunk/tests/simulate/jquery.simulate.js
this might be a little too processor intensive but going over the whole list of div elements on a page, finding their positions and sizes then testing if they're under the mouse. i don't think i'd want to do that to a browser though.
You might find it's more efficient to traverse the DOM tree once when the page is loaded, get all elements' positions and sizes, and store them in an array/hash/etc. If you design the data structure well, you should be able to find an element at the given coordinates fairly quickly when you need it later.
Consider how often you will need to detect an element, and compare that to how often the elements on the page will change. You would be balancing the number of times you have to re-compute all the element locations (an expensive computation) against the number of times you'd actually use the computed information (relatively cheap, I hope).