AngularJS Directives - Widget Directive

HTML

<script src="http://code.angularjs.org/angular-1.0.0rc5.min.js"></script>
<div ng-app="animateApp" ng-controller="AnimateCtrl">


        <div class="boundingBox">

           <ball ng-repeat="shape in shapes"
                    x="shape.x"
                    y="shape.y"
                    color="shape.color" />

        </div>
       <p>
        asd
       </p>

</div>

CSS

.boundingBox {
    width: 600px;
    height: 600px;
    background-color: #333333;
    margin:20px;
}


.circle {
    display:block;
    position:absolute;
    height: 20px;
    width: 20px;
    background-color: #999;
    -moz-border-radius: 15px;
    -webkit-border-radius: 15px;
    border-radius: 15px;
}

.box {
    display:block;
    position:absolute;
    height: 20px;
    width: 20px;

}

#controls {
    position: absolute;
    top: 620px;
}

JavaScript

var module = angular
        .module('animateApp', [])
        .directive('ball', function ($defer) {
            return {
                restrict:'E',
                link:function (scope, element, attrs) {
                    element.addClass('circle');

                    scope.$watch(attrs.x, function (x) {
                        element.css('left', x + 'px');
                    });
                    scope.$watch(attrs.y, function (y) {
                        element.css('top', y + 'px');
                    });
                    scope.$watch(attrs.color, function (color) {
                        element.css('backgroundColor', color);
                    });
                }
            };
        })
       .factory('animate', function($window, $rootScope) {
          var requestAnimationFrame = $window.requestAnimationFrame ||
               $window.mozRequestAnimationFrame ||
               $window.msRequestAnimationFrame ||
               $window.webkitRequestAnimationFrame;
           
          
           return function(tick) {
               requestAnimationFrame(function() {
                   $rootScope.$apply(tick);
               });
           };
       });

function animator(shapes, animate) {
    (function tick() {
        var i;
        var now = new Date().getTime();
        var maxX = 600;
        var maxY = 600;
        var now = new Date().getTime();

        for (i = 0; i < shapes.length; i++) {
            var shape = shapes[i];
            var elapsed = (shape.timestamp || now) - now;

            shape.timestamp = now;
            shape.x += elapsed * shape.velX / 1000;
            shape.y += elapsed * shape.velY / 1000;

            if (shape.x > maxX) {
                shape.x = 2 * maxX - shape.x;
                shape.velX *= -1;
            }
            if (shape.x < 30) {
                shape.x = 30;
                shape.velX *= -1;
            }

            if (shape.y > maxY) {
                shape.y = 2 * maxY...