ng-animate-ref allows to create a transition from one dom node to another.
ng-animate uses all the css styles like position, font-size, font-color and more from the first dom element and the second dom element and creates a css 3 animation to move the element from state a to state b.
This is exactly what I need but unfortunately I can't use Angular 1 in the current project.
Is there any reusable way to achieve the same css3 animation without moving all styles from my css files to javascript?
To illustrate the problem please see the following example. As you can see the example has no custom javascript animation code at all but only javascript code which handles the state logic switching elements from list a to b.
The animation definition is written in pure css.
Demo:
https://codepen.io/jonespen/pen/avBZpO/
Preview:
TL;DR # Use CSS animations for simpler "one-shot" transitions, like toggling UI element states. Use JavaScript animations when you want to have advanced effects like bouncing, stop, pause, rewind, or slow down.
CSS allows animation of HTML elements without using JavaScript or Flash! In this chapter you will learn about the following properties: @keyframes.
Inserting Nodes into the DOM The methods appendChild() and insertBefore() are used to add items to the beginning, middle, or end of a parent element, and replaceChild() is used to replace an old node with a new node.
Animation CodeJavaScript animations are done by programming gradual changes in an element's style. The changes are called by a timer. When the timer interval is small, the animation looks continuous.
Of course, jQuery animate can achieve it without any plugins.
Maybe there are not many lines of code, but they do have some complexity.
Here is what you want ( ps: jquery-ui only use to change color ).
$(document).ready(function() {    var animating = false,      durtion = 300;    $('.items').on("click", ".items-link", function() {      if (animating) return;      animating = true;      var $this = $(this),        dir = $this.parent().hasClass("items-l") ? "r" : "l",        color = dir == "l" ? "#0000FF" : "#F00000",        index = $this.attr("data-index");        var toItems = $('.items-' + dir),        itemsLinks = toItems.find(".items-link"),        newEle = $this.clone(true),        nextEle = $this.next(),        toEle;        if (itemsLinks.length == 0) {        toItems.append(newEle)      } else {        itemsLinks.each(function() {          if ($(this).attr("data-index") > index) {            toEle = $(this);            return false;          }        });        if (toEle) {          toEle.before(newEle).animate({            "marginTop": $this.outerHeight()          }, durtion, function() {            toEle.css("marginTop", 0);          });        } else {          toEle = itemsLinks.last();          toEle.after(newEle)        }      }        nextEle && nextEle.css("marginTop", $this.outerHeight())        .animate({          "marginTop": 0        }, durtion);        var animate = newEle.position();      animate["background-color"] = color;      newEle.hide() && $this.css('position', 'absolute')        .animate(animate, durtion, function() {          newEle.show();          $this.remove();          animating = false;        });    });  });  .items {    padding: 0;    -webkit-transition: 300ms linear all;    transition: 300ms linear all;  }  .items.items-l {    float: left  }  .items.items-r {    float: right  }  .items.items-l a {    background: #0000FF  }  .items.items-r a {    background: #F00000  }  .items a,  .items-link {    color: #fff;    padding: 10px;    display: block;  }  .main {    width: 100%;  }  <script type="text/javascript" src="//code.jquery.com/jquery-1.9.1.js">  </script>  <script type="text/javascript" src="//code.jquery.com/ui/1.9.2/jquery-ui.js">  </script>  <link rel="stylesheet" type="text/css" href="//code.jquery.com/ui/1.9.2/themes/base/jquery-ui.css">  <div class="main">    <div class="items items-l">      <a class="items-link" data-index="1" href="#">Item 1</a>      <a class="items-link" data-index="2" href="#">Item 2</a>      <a class="items-link" data-index="3" href="#">Item 3</a>       <a class="items-link" data-index="4" href="#">Item 4</a>      </div>      <div class="items items-r">        <a href="#" class="items-link" data-index="5">Item 5</a>        <a href="#" class="items-link" data-index="6">Item 6</a>        <a href="#" class="items-link" data-index="7">Item 7</a>        <a href="#" class="items-link" data-index="8">Item 8</a>    </div>      A plain javascript solution that uses:
HTMLElement.getBoundingClientRect to find differences between the old and new positions of elementtransition to animatetransform to translateThe core idea is to have the browser only calculate/reflow the DOM once. We'll take care of the transition between the initial state and this new one ourselves.
By only transitioning (a) the GPU accelerated transform property, on (b) a small selection of elements (all <li> elements), we'll try to ensure a high frame rate.
// Store references to DOM elements we'll need:  var lists = [    document.querySelector(".js-list0"),    document.querySelector(".js-list1")  ];  var items = Array.prototype.slice.call(document.querySelectorAll("li"));    // The function that triggers the css transitions:  var transition = (function() {     var keyIndex = 0,        bboxesBefore = {},        bboxesAfter = {},        storeBbox = function(obj, element) {          var key = element.getAttribute("data-key");          if (!key) {            element.setAttribute("data-key", "KEY_" + keyIndex++);            return storeBbox(obj, element);          }                    obj[key] = element.getBoundingClientRect();        },        storeBboxes = function(obj, elements) {          return elements.forEach(storeBbox.bind(null, obj));        };        // `action` is a function that modifies the DOM from state *before* to state *after*    // `elements` is an array of HTMLElements which we want to monitor and transition    return function(action, elements) {      if (!elements || !elements.length) {        return action();      }            // Store old position      storeBboxes(bboxesBefore, elements);            // Turn off animation      document.body.classList.toggle("animated", false);            // Call action that moves stuff around      action();            // Store new position      storeBboxes(bboxesAfter, elements);            // Transform each element from its new position to its old one      elements.forEach(function(el) {        var key = el.getAttribute("data-key");        var bbox = {          before: bboxesBefore[key],          after: bboxesAfter[key]        };                var dx = bbox.before.left - bbox.after.left;        var dy = bbox.before.top - bbox.after.top;                el.style.transform = "translate3d(" + dx + "px," + dy + "px, 0)";      });        // Force repaint      elements[0].parentElement.offsetHeight;        // Turn on CSS animations      document.body.classList.toggle("animated", true);           // Remove translation to animate to natural position      elements.forEach(function(el) {        el.style.transform = "";      });    };  }());    // Event handler & sorting/moving logic  document.querySelector("div").addEventListener("click", function(e) {    var currentList = e.target.getAttribute("data-list");    if (currentList) {      var targetIndex = e.target.getAttribute("data-index");      var nextIndex = 0;        // Get the next list from the lists array      var newListIndex = (+currentList + 1) % lists.length;      var newList = lists[newListIndex];            for (nextIndex; nextIndex < newList.children.length; nextIndex++) {        if (newList.children[nextIndex].getAttribute("data-index") > targetIndex) {          break;        }      }            // Call the transition      transition(function() {        newList.insertBefore(e.target, newList.children[nextIndex]);        e.target.setAttribute("data-list", newListIndex);      }, items);    }  });  div { display: flex; justify-content: space-between; }      .animated li {    transition: transform .5s ease-in-out;  }  <h2>Example</h2>  <div>    <ul class="js-list0">      <li data-index="0" data-list="0">Item 1</li>      <li data-index="3" data-list="0">Item 2</li>      <li data-index="5" data-list="0">Item 4</li>      <li data-index="7" data-list="0">Item 6</li>    </ul>      <ul class="js-list1">      <li data-index="4" data-list="1">Item 3</li>      <li data-index="6" data-list="1">Item 5</li>    </ul>  </div>  Edit:
To add support for other properties you'd like to animate, follow this 4 step approach:
Add the css rule to the .animated transition property:
transition: transform .5s ease-in-out,             background-color .5s ease-in-out;  Store the properties computed style before you modify the DOM:
obj[key].bgColor = window   .getComputedStyle(element, null)   .getPropertyValue("background-color");  After modifying, quickly set a temporary override for the property, like we already did for the transform prop.
el.style.backgroundColor = bbox.before.bgColor;  After turning on the css animations, remove the temporary override to trigger the css transition:
el.style.backgroundColor = "";  In action: http://codepen.io/anon/pen/pELzdr
Please note that css transitions work very well on some properties, like transform and opacity, while they might perform worse on others (like height, which usually triggers repaints). Make sure you monitor your frame rates to prevent performance issues!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With