Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Passing parameters to JS Animation in Angular

Tags:

angularjs

I wrote this this Plunker containing a simple JS Animation, done via jQuery.css / jQuery.animate.

Short Description:

  • 3 Rectangles are shown
  • Button "Randomize" randomizes width/height of the Rectangles
  • This change in widht/height should be animated

I need to be able to pass the changed width/height as parameters to the animations addClass function. The addClass defintion looks like this:

addClass(element, className, doneCallback)

So I added my custom values to the prototype of the element. E.g LoC 53

Object.getPrototypeOf(element).custom_bs_width = newVal[attrs.id].width;

And access them in the addClass function to animate. LoC 65+

myApp.animation('.updateRectangles', function() {
return {
    addClass : function(element, className, done) {
      jQuery(element).animate({
        width:  Object.getPrototypeOf(element).custom_bs_width,

Is this a correct way? If not, what alternative exists to pass parameters to a JS Animation. I excluded CSS Animation and CSS Keyframe Animation as imho there is no way to pass parameters. Agree?

like image 931
ilmgb Avatar asked Jan 10 '14 08:01

ilmgb


1 Answers

As you suspected, "passing parameters to addClass" is a really twisted hack.

Angular animation is built around CSS classes (hence the addClass/removeClass) and thus, works well with CSS3 Transitions. This system is meant to work so that DOM elements in ng-repeat automatically sets CSS classes to trigger animation when items are added, moved or removed. That has nothing to do with "custom" animations like I think is your intention here.

One option is to use plain CSS3 Transitions (which is not the same as CSS Animations) and simply modify the element's size/positions/color using standard Angular data binding via ng-style. The CSS Transitions, if properly setup in CSS, will kick in automatically. I created a simple method (computeCSS) that "converts" the "item's data"to a ng-style-friendly structure. Here's code (with a bonus that smoothly fades the color too).

http://plnkr.co/edit/oMOUiV5Sk6YusPpOqUQz?p=preview

Added a CSS3 Transition of 600ms:

<style>
  .my-rectangles {
    position:absolute;
   -webkit-transition: width 0.6s, height 0.6s, left 0.6s, top 0.6s, background-color 0.6s;
   transition: width 0.6s, height 0.6s, left 0.6s, top 0.6s, background-color 0.6s;
  }
</style>

Here's the code:

var myApp = angular.module("MyApp", ["ngAnimate"]);

myApp.controller('MainCtrl', function($scope) {
  //nothing to declare
});

//general directive for the rectangles
myApp.directive('rectangles', function() {
  return{
    restrict: 'E',
    template: '<div style="position:relative; width: 200px; height: 200px; background-color: #646464">' +
                  '<div ng-repeat="item in items" id="{{$index}}" class="my-rectangles" ng-style="computeCSS(item)"></div>' +
              '</div>',
    controller: function($scope) {

      $scope.computeCSS = function(item) {
        return { 
          width: item.width+"px", 
          left: item.left+"px", 
          top: item.top+"px", 
          height: item.height+"px", 
          'background-color':item.color
        };
      }

      $scope.items = [
        {width: 10, left: 10, top: 10, height: 10, color:'#4C8B71'},
        {width: 10, left: 80, top: 10, height: 10, color:'#F3D698'},
        {width: 10, left: 160, top: 10, height: 10, color:'#D25F45'}
      ];

      $scope.randomize = function() {
        $scope.items.forEach(function(item) {
          item.width = Math.random() * (40 - 10) + 10;
          item.height = item.width;
          item.color = "#" + (Math.round(Math.random()*0xFFFFFF)).toString(16);
        })
      }
    }
  }    
});
like image 113
Bernard Avatar answered Nov 15 '22 07:11

Bernard