var app = angular.module('plunker', ['ui.bootstrap']);

app.value('pusheen', {name: 'pusheen', width:96, height: 100, nframes: 4, rframes: 2,   url: 'https://m.ak.fbcdn.net/dragon.ak/hphotos-ak-ash3/s296x100/851578_185127901661476_1172208870_n.png'});
app.value('anooki', {name: 'anooki', width:480, height:480, nframes: 13, rframes:4 , url: 'https://m.ak.fbcdn.net/dragon.ak/hphotos-ak-prn1/p480x480/851584_629578030410264_540358936_n.png'} )
app.value('beast', {name: 'beast', width:150, height:100, nframes: 5, rframes: 3, url: 'https://m.ak.fbcdn.net/dragon.ak/hphotos-ak-prn1/s296x100/851560_668853719808805_601127660_n.png'} )


app.controller('MainCtrl', function($scope, pusheen, anooki, beast, $modal) {
    $scope.stickers = [pusheen, anooki, beast];
    
  $scope.isAnimated = false;  
  $scope.animation = $scope.stickers[1];
  
  $scope.doAnimation = function() {
    $scope.isAnimated = !$scope.isAnimated;
  }
  
  $scope.open = function () {

    var modalInstance = $modal.open({
      templateUrl: 'Sticker.html',
      controller: ModalInstanceCtrl,
      
      resolve: {
        items: function () {
          return $scope.stickers;
        }
      }
    });

    modalInstance.result.then(function (selectedItem) {
      $scope.animation = selectedItem;
      $scope.isAnimated = false;
    }, function () {
      //$log.info('Modal dismissed at: ' + new Date());
    });
  };
  
});

var ModalInstanceCtrl =  function ($scope, $modalInstance, items) {

  $scope.items = items;
  $scope.selected = {
    item: $scope.items[0]
  };

  $scope.ok = function () {
    $modalInstance.close($scope.selected.item);
  };
 
  $scope.changeSticker = function(item) {
    $scope.selected.item = item;
    $modalInstance.close($scope.selected.item);
    
  };

  $scope.cancel = function () {
    $modalInstance.dismiss('cancel');
  };
};

/* 
 background-image: url(https://m.ak.fbcdn.net/dragon.ak/hphotos-ak-prn1/p480x480/851584_629578030410264_540358936_n.png);
        background-size: 480px;
        cursor: pointer;
        height: 120px;
        width: 120px;
        background-position: 0px 0px;  
*/


app.directive('sticker', function(timeFunctions){
    return {
      restrict: 'AE',
      replace: true,
      
    scope: {
      isAnimated: '=isanimated',
      Animation: '=animation',
      speed: '=speed'
    },
    // "background-image: url({{$scope.Animation.url}}); width: {{$scope.Animation.width}} height: {{$scope.Animation.height}}"
     template: '<div></div>',
     link: function(scope, element, attrs) {
       // se puede calcular la posicion pero para este ejemplo tenemos un array
     scope.width = 0;
     scope.height = 0;
     scope.index = 0;
     scope.nRows = 0;
     scope.nCols = 0;
     scope.nFrames = 0;
     
      scope.$watch('Animation', function(Animation) {
        // this is the Animation we will use
        
        if (Animation) {
          console.log(Animation.name);
          scope.nRows = Math.ceil(Animation.nframes / Animation.rframes);
          scope.index = 0;
          scope.nCols = Animation.rframes;  
          scope.nFrames = Animation.nframes;
          scope.width = Animation.width / Animation.rframes;
          scope.height = Animation.height / scope.nRows;
          element.css({ 'backgroundPosition': '0 0', 'background-image': 'url(' + Animation.url + ')', 'width': scope.width + 'px','height': scope.height + 'px'} );
          scope.isAnimated = true; 
        }
      });
      
      scope.$watch('isAnimated', function(isAnimated) {
          if (scope.isAnimated) {
              startAnimation();
          } else {
             timeFunctions.$clearInterval( scope.animateTimeout );
          }
      });
      
      function startAnimation() {
          scope.animateTimeout = timeFunctions.$setInterval(animateBg, scope.speed, scope);  
      }

      function animateBg() {
        element.css({'backgroundPosition': calcBgPosition(scope.index, scope.nRows, scope.nCols, scope.nFrames, scope.width, scope.height )});
        scope.index++;
      }
      
       element.bind('click', function(e) {
          e.preventDefault();
          scope.$apply(function() {
             scope.isAnimated = !scope.isAnimated;
            
          });
          
          
        });
        
      
      
      function calcBgPosition(index, nRows, nCols, nFrames, width, height) {
        var i = index % nFrames;
        var x=0,y=0;
      
        x = (i % nCols) * width * -1;
        y = Math.floor(i / (nCols)) * height * -1;
        
        //console.log(index + ':' + i + ':'+ nRows + ':' + nCols + '  ' + x + 'px ' + y + 'px');
        return x + 'px ' + y + 'px';
      }
      
      }
    }
  });


  
  //http://stackoverflow.com/questions/14237070/using-setinterval-in-angularjs-factory/14238039#14238039
app.factory('timeFunctions', [ "$timeout",

  function timeFunctions($timeout) {
    var _intervals = {}, _intervalUID = 1;

    return {

      $setInterval: function(operation, interval, $scope) {
        var _internalId = _intervalUID++;

        _intervals[ _internalId ] = $timeout(function intervalOperation(){
            operation( $scope || undefined );
            _intervals[ _internalId ] = $timeout(intervalOperation, interval);
        }, interval);

        return _internalId;
      },

      $clearInterval: function(id) {
        return $timeout.cancel( _intervals[ id ] );
      }, 
      timeout: function() {
        return $timeout;
      }
    }
  }
]);




<!DOCTYPE html>
<html ng-app="plunker">
  <head>
    <meta charset="utf-8" />
    <title>AngularJS Plunker</title>
    <script>document.write('<base href="' + document.location + '" />');</script>
    <style>
      #animator {
        background-image: url(https://m.ak.fbcdn.net/dragon.ak/hphotos-ak-prn1/p480x480/851584_629578030410264_540358936_n.png);
        background-size: 480px;
        cursor: pointer;
        height: 120px;
        width: 120px;
        background-position: 0px 0px;  
        }
    </style>
    
    <script data-require="angular.js@1.1.x" src="http://ajax.googleapis.com/ajax/libs/angularjs/1.1.5/angular.js" data-semver="1.1.5"></script>
    <script src="http://angular-ui.github.io/bootstrap/ui-bootstrap-tpls-0.6.0.js"></script>
    
    <link href="//netdna.bootstrapcdn.com/twitter-bootstrap/2.3.1/css/bootstrap-combined.min.css" rel="stylesheet">
    
    <script src="app.js"></script>

  </head>

  <body ng-controller='MainCtrl'>
  <h1>Facebook Stickers - Animados con Angular</h1>
    
    {{isAnimated}}
    <button ng-click='open()'>Stickers</button>
    <button ng-click='doAnimation()'>Go Test</button>
    
    <sticker animation='animation' isanimated='isAnimated' speed='200'></sticker>
    
    
    
    
    
     <script type="text/ng-template" id="Sticker.html">
        <div class="modal-header">
            <h3>Select your Sticker</h3>
        </div>
        <div class="modal-body">
            
                <div ng-repeat="item in items">
                   <a ng-click="changeSticker(item)"><sticker animation='item' isanimated='false' speed='0'></sticker></a>
                </div>
           
        </div>
        <div class="modal-footer">
            <button class="btn btn-primary" ng-click="ok()">OK</button>
            <button class="btn btn-warning" ng-click="cancel()">Cancel</button>
        </div>
    </script>

    
    
  </body>

</html>
/* Put your css in here */