3

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.,

  1. Have the div JUMP (instantly) to 100px, then transition (over 400ms) to 200px
  2. 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:

  1. Remove the event listeners for the transitionEnd event
  2. Set the transition property to none
  3. Change the position of the div (e.g., [div].style.transform = translate3d([starting position]px, 0px, 0px))
  4. Add the event listeners for the transitionEnd event
  5. Set the transition property to have a transition (e.g., [div].style.transition:all 0.4s ease-in)
  6. 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:

  1. Remove the transitions class
  2. Apply the starting position
  3. Restore the transitions class
  4. 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!

1
  • Please check the updated answer. You no longer need to add an arbitrary delay. Commented Nov 19, 2013 at 17:40

1 Answer 1

2

I think you have over-complicated this :). Here's how I'd approach this problem:

  1. Add a class to your divs, say movable.
  2. Declare all your transition rules and transitionEnd callbacks for .movable.
  3. Nothing to do if you want to move your div smoothly.
  4. 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.

Sign up to request clarification or add additional context in comments.

5 Comments

This doesn't quite seem to work. Conceptually, I need to do four things: 1) Remove the "movable" class, 2) Set the starting position, 3) Restore the moveable class, 4) Set the ending position (which should transition). The problem seems to be that when you execute all four steps in a JavaScript function - it doesn't seem to execute all of them. Instead, it "nets" them out. I.e., it concludes that the "net" result of 1) and 3) is that the class SHOULD have the "moveable" class, and the net result of 2) and 4) is that the element should just move to the ending position.
In other words, it seems to just ignore steps 1 and 2. On the other hand - if I execute steps 1 and 2, then create a timeout that executes 3 and 4 after a short (200ms) delay - it works. But I don't like having to utilize a delay.
I have never seen Javascript or jquery netting the results of successive operations. They may be happening so fast that you are unable to see them. Could you create a fiddle where I can verify what you are seeing?
Chandranshu - first - thanks for your help. Here's two fiddles I set up. In this one, I execute all 4 steps in a single function: jsfiddle.net/bUvX3 In the next one, I execute steps 3 and 4 after a 50ms delay: jsfiddle.net/2mhcv As you'll see, only the one with the delay seems to work. Of course, I could just be making a stupid mistake...
Ah, I get it. There is a difference between what you wanted and what I suggested and hence between what I suggested and what you implemented. I didn't want to move the div using the transformation style. I thought the div is placed in some container and we know its current left/right position and we could just change that. Sets of transforms (and 3d transforms in particular) will execute together unless an intentional delay is introduced.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.