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' });
Related
All,
I've got a situation in which I'm using CSS transforms/transitions to animate the horizontal position of a div element. Specifically, I'm using...
// in CSS
myDiv {
transition: transform 0.4s ease-in;
}
// in JavaScript, where "div" contains a reference to the div element
div.style.transform = translate3d(Npx, 0px, 0px);
...and it works well. That is, every time I call that line of JavaScript with a new value for N, the div smoothly animates from its current position to its new position.
However, there are times when I need position the div first WITHOUT a transition, then MOVE it WITH a transition. E.g.,
Have the div JUMP (instantly) to 100px, then transition (over 400ms) to 200px
Later, JUMP the div to 500px (without a transition), then transition it to 600px
In other words, I'd like to be able to move a div, and be able to control whether the new position is applied instantaneously, or with a transition.
Complicating matters, I have event listeners that fire when the transition is complete; these listeners should NOT fire if/when I move the div without a transition. I'm also supporting multiple browsers, so I have to deal with all the vendor prefixes.
In pseudo-code, I guess it would look something like this:
Remove the event listeners for the transitionEnd event
Set the transition property to none
Change the position of the div (e.g., [div].style.transform = translate3d([starting position]px, 0px, 0px))
Add the event listeners for the transitionEnd event
Set the transition property to have a transition (e.g., [div].style.transition:all 0.4s ease-in)
Change the position of the div (e.g., [div].style.transform = translate3d([ending position]px, 0px, 0px))
With all the vendor prefixes, that's too messy and complicated to be the best way to accomplish this. (I'm not even sure if it works...)
So, what's the best way to toggle transitions/transformations on and off?
[UPDATE]
Thanks to a suggestion from Chandranshu, I've tried toggling a class that includes the transitions.
So, my pseudocode looks like this:
Remove the transitions class
Apply the starting position
Restore the transitions class
Apply the ending position
However, it looks like, if I execute all four steps in a single JavaScript function - it seems to ignore steps 1-2, as though it's "netting" the results of all four steps.
Here's a jsfiddle that demonstrates this: http://jsfiddle.net/bUvX3/
Instead - if I execute steps 1 and 2, then execute steps 3 and 4 after a short delay (e.g., by using a setTimeout), it works: http://jsfiddle.net/2mhcv/
So, I guess that's a solution, except that I really don't like having to add an arbitrary delay, especially when so much emphasis is placed on fast, responsive UIs.
Thanks in advance!
I think you have over-complicated this :). Here's how I'd approach this problem:
Add a class to your divs, say movable.
Declare all your transition rules and transitionEnd callbacks for .movable.
Nothing to do if you want to move your div smoothly.
When you need to move your div w/o a transition, remove this class, move your div and add this class back: $('div').removeClass('movable').animate({transform: 'translate3d(...)' }).addClass('movable')
UPDATE:
Finally, I've got what you wanted: http://jsfiddle.net/2mhcv/1/. The only change here is that instead of a delay of 20ms, I'm using a delay of 0! setTimeout() causes a repaint to be triggered and that ensures that the first animation is executed before the next one begins.
UPDATE 2:
This version works without a setTimeout() call: http://jsfiddle.net/2mhcv/2/. Realizing that a repaint is all that is needed, I just added a line there to read a compute CSS property such as display. You could have read any other computed property to get the same effect.
i'm trying to create the same nice effect of and overlayed arrow (ie desktop version of chrome) when you swipe left or right in for a mobile browser.
I use javascript and jQuery and for now i can show the arrow when I swipe. I managed to have the distance of the swipe but i can't find a way to link the two so i only show a portion of the arrow in relation with the distance !
$('#arrow').show('slide',{direction: 'right'},1000);
$('#arrow').fadeIn();
$('#arrow').fadeOut();
I'm trying to do it also with animate() but i'm still stuck :S
Thanks for the help
You'll need three values: start, end, current.
In your case, you'll need to determine what is the start end value.
I would say use the width of your swipe-able area (screen), which would give you 0 and x (where x is the width of your swipe-able area). You already have current, which is the distance between start and and where your actual swipe ends (width of swipe, perhaps?).
Once you have those values, you can derive a percentage (between 0 and 1) and apply it to your arrow using #mikakun's suggestion. The arrow graphic will either need to be absolutely positioned in the container or set as a background image of the container. That will give you the effect of only seeing a percentage of the arrow as the container expands to reveal more. A nice effect would be to have a semi-transparent/greyed out duplicate of the full arrow in behind the one you are revealing.
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 want to animate between "default" states/positions for a div. For example:
Div absolutely positioned with a class, to be on the left of the screen. Class is removed via JS (or replaced) and position is now relative. The default relative position is actually on the opposite side of the screen. I want to animate this.
Something like a dock, various divs as icons in display-inline, centered horizontally on the dock. If I "delete" one of the icons, the rest will shift a bit to recenter. I want to animate them shifting to fill the gap.
Transition: all does not work (I assume because there was no predefined values for the position) so is this even possible? Are there JS solutions to this?
It's possible exactly the way you described it. Here's a live example of how it's done.
http://jsfiddle.net/nDr4y/3/
You can also remove the transition from css and use jquery to animate the element with pure JS. The syntax looks like this:
// in the object are the css properties you want to animate,
// the second argument is how long you want it to take in ms
$('.el').animate({ left: 100 }, 1000);
You just need to figure out the destination coordinates and set it using jQuery, or whatever framework you use. Other than that, it's totally possible.
http://jsfiddle.net/Kd72u/
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/