Mooseman
Mooseman

Reputation: 18891

How to transition a div between two parents?

I have two containers:

<div class="left">
    <div id="myDiv">A Div</div>
    <div id="myDiv2">A Div</div>
</div>
<div class="right">
    <div id="myDiv3">A Div</div>
</div>

The first contains div elements, which are moved with the following jQuery:

$(".left > div").click(function(){
    $(this).appendTo('.right');
});

The above, however, provides no animation. I would like to use a CSS transition to animate each div between the two parent elements (From .left to .right).

By the way, this is my CSS:

.left, .right{
    position: absolute;
    display: block;
    box-sizing: border-box;
    width: 50%;
    height: 100%;
}
.left{background:red;}
.right{background:green; left: 50%;}
.left > div, .right > div{
    display: block;
    height: 100px;
    width: 100px;
    margin: 10px;
    float: left;
    background: #fff;
    color: #000;
}

And a Fiddle: http://jsfiddle.net/x270Lndz/


I figure I need to get coordinates and transition between them, outside both .left and .right.

Upvotes: 6

Views: 2715

Answers (4)

Mooseman
Mooseman

Reputation: 18891

I wrote a jQuery plugin:

$.fn.transitionTo = function(target){
    this.each(function(){
        $this = $(this);
        marginLeft = parseInt($this.css('marginLeft').replace("px", "")); 
        marginTop = parseInt($this.css('marginTop').replace("px", ""));
        offset = $this.offset();
        $new = $this.clone().appendTo(target);
        offsetNew = $new.css('opacity',0).offset();
        $this.css({
            position: 'absolute',
            left: offset.left - marginLeft,
            top: offset.top - marginTop
        }).appendTo("body");
        setTimeout(function(a,b){
            a.css({
                left: offsetNew.left - marginLeft,
                top: offsetNew.top - marginTop
            });
            setTimeout(function(a,b){
                b.replaceWith(a.removeAttr('style'));
            },2000,a,b); //Anim time
        },10,$this,$new);
    });
};

It is called similarly to .appendTo:

$(".left > div").click(function(){
    $(this).transitionTo('.right');
});

...and only requires transition: top 2s ease, left 2s ease; on the div.

Fiddle: http://jsfiddle.net/d9yxrmvo/1/


The only known issue with this plugin is the lack of support for animating the original element's siblings.

Upvotes: 0

Katana314
Katana314

Reputation: 8620

Ultimately, this is going to be a lot of work, and I don't think I have the time to write every step out in full. But, if you're committed, here goes:

  1. Call getBoundingClientRect() or similar on the first element to get its absolute document position relative to the document / viewport.
  2. Use the same function, and getComputedStyle()s padding to determine the exact pixel at which content would begin in the second div.
  3. Determine the difference between the two coordinates, in order to fake the transition while the elements are still inside their first parent. (Or, move them first, and fake the transition after)
  4. Apply the correct transform: translate style to the elements, so that they'll appear to move into the other container. (This is assuming you have the transition properties set up correctly in CSS)
  5. On the transitionend event, turn off transitions, remove the transform property, and do the actual child move.
  6. Pat yourself on the back and go home early.

So there you have it. There's likely going to be a lot of math involved and small additions/subtractions I'm not able to predict. Hopefully, that outline helps you get started at least. You might also be lucky enough to find an animation library that does all of this for you. (Also note that I assumed the presence of several functions not supported on all browsers, so check to make sure they're okay by your book)

Upvotes: 0

Waxi
Waxi

Reputation: 1651

This has already been answered: https://stackoverflow.com/a/974765/2725684

The problem is 2 parts, moving elements in the DOM, and animating that movement, but the suggested is:

  1. Store the position of the div, in its resting state, in the first column.
  2. Append the div to the second column, store that position.
  3. Turn off the visibility of the div.
  4. Create a clone of the div, positioned where the resting state one was at.
  5. Animate this clone across to the position of the appended div.
  6. Turn off the visibility of this clone.
  7. Turn back on the original div that was appended.

The javascript/jquery will execute this so fast you won't see the turning off/on of the divs and it will just appear as if the div they are seeing is the only one that ever existed.

Upvotes: 5

Pixelomo
Pixelomo

Reputation: 6737

Try adding transition: 0.5s ease-in to the .left div

Upvotes: 0

Related Questions