How to make a div fly to another div after appendTo

Viewed 318

I have elements that I want to move around to other divs when they are clicked. I found appendTo, but I don't know how to let the element fly to the other div in transition.

<div id="top">
  <button id="b1">B1</button>
</div>
<br>
<br>
<br>
<br>
<div id="bottom">
  <button id="b2">B2</button>
</div>

<script>
$('#b1').click(function() {
  $('#b1').appendTo($('#bottom'));
})

$('#b2').click(function() {
  $('#b2').appendTo($('#top'));
})
</script>

Is there a simple way to make the buttons 'fly' after they are clicked? For now, I just make them fade out and into the new div.

2 Answers
  1. create an element's "flying clone" as position:fixed at current coordinates.
  2. append the element to destination
  3. make the element hidden using visibility:hidden or opacity:0
  4. animate the clone from start coordinates to the element's new coordinates
  5. destroy the clone
  6. make the element visible
  7. prevent fly if element is already in destination (i.e: on subsequent calls)

/** 
 * Fly element to destination parent
 * Use like: flyMeTo("#bird", "#destinationParent")
 * @param el {String} Selector (or `this`) of the flying element
 * @param destination {String} Destination parent selector
 * @param prepend {Boolean} Optional. Set to true to use prepend (instead of append)
 */
function flyMeTo(elem, destination, prepend) {

  var $elem = $(elem);
  var $dest = $(destination);
  
  // Early exit - if already in destination
  if($elem.parent().is(destination)) return;
  
  var $klon = $elem.clone().insertAfter($elem);
  var start = elem.getBoundingClientRect();

  $klon.css({position:"fixed", zIndex:9999, left:start.left, top:start.top, pointerEvents:'none'});
  $elem.css({opacity:0})[prepend?'prependTo':'appendTo']( $dest );

  var end = elem.getBoundingClientRect(); // Get new coordinates after append/prepend
  $klon.animate({left:end.left, top:end.top}, 600, function() {
    $klon.remove();         // Remove flying clone once it reaches destination
    $elem.css({opacity:1}); // Show original Element
  });
}


// DEMO:
$('#b1').click(function() {
  flyMeTo( this, '#bottom', true ); // By passing `true` it will prepend!
});
$('#b2').click(function() {
  flyMeTo( this, '#top' );
});
body {
  height: 200vh;
}
<br>
<br>
<br>
<div id="top">
  <button id="b1">B1</button>
</div>
<br>
<br>
<br>
<br>
<div id="bottom">
  <button id="b2">B2</button>
</div>

<script src="//code.jquery.com/jquery-3.1.0.js"></script>

I stripped down Roko's answer to see which methods do what.

function flyMeTo( orig, destination ) {
  var $copy = $(orig).clone().insertAfter($(orig)); // duplicate the original button element

  $copy.css({position:"fixed"}); // dunno what this is for
  $(orig).css({opacity:0}).appendTo(destination); // make the orig invisible then append it to the other div still invisible

  var end = orig.getBoundingClientRect(); // now that the orig is at the new location, get its position
  $copy.animate({left:end.left, top:end.top}); // animate the duplicate to make it go to that position  
}
Related