Take the 2-minute tour ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

I am currently trying to do a CSS3 animation in Angular.js.
Before animating I try to set the initial css properties using Javascript.
So, is there a way to initialize an animation using Javascript and then continue the animation using CSS3?

My situation:
When the user clicks on a div, a dialog should appear. The dialog should start out exactly over the original div (same size, same position), and then grow to a larger size.

I am able to animate the dialog from a predefined position and size:

CSS:

.dialog {
    position: absolute;
    z-index: 10;
    width:600px;
    height:400px;
    margin-left: -300px;
    left:50%;
    margin-top: 50px;
}
.dialogHolder.ng-enter .dialog {
    transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 1s;
    width:0;
    height:0;
    margin-left: 0px;
}
.dialogHolder.ng-enter-active .dialog {
    width:600px;
    height:400px;
    margin-left: -300px;
}

I would like to animate the dialog starting at the size of the clicked div. So far my code (not working yet) looks like this:

HTML:

<div ng-repeat="course in data.courses" ng-click="showDialog($event)">
    {{ course.cursus }}
</div>

<!-- Placeholder for blokDialogs -->
<div class="dialogHolder" ng-include="dialogTemplate.url">
    DIALOG WILL BE LOADED HERE
</div>

Javascript:

app.controller('blockController', function($scope) {

    $scope.showDialog = function(evt) {
        // get position and size of the course block
        $scope.dialogTemplate.clientRect = evt.target.getBoundingClientRect();

        // load the html to show the dialog
        $scope.dialogTemplate.url = 'partials/blokDialog.html';

        // SHOULD I DO SOMETHING HERE?
    };

});

// OR SHOULD I DO SOMETHING LIKE THIS?
app.animation('.dialogHolder', function(){
    return {
        // SOMEHOW SET THE WIDTH, HEIGHT, TOP, LEFT OF .dialog
    };
});

I'd prefer to do this without jQuery to keep the page weight low.

Regards, Hendrik Jan

share|improve this question
add comment

2 Answers

You want to use ng-animate http://docs.angularjs.org/api/ngAnimate

If you are using ng-repeat, you can animate when elements enter, leave and move around your repeater. The magic is that you don't even have to put an extra directive in your html, just define your CSS animations accordingly.

So in your case something like this

.repeater.ng-enter, .repeater.ng-leave, .repeater.ng-move {
  -webkit-transition:0.5s linear all;
  transition:0.5s linear all;
}

.repeater.ng-enter { }
.repeater.ng-enter-active { }
.repeater.ng-leave { }        
.repeater.ng-leave-active { }
.repeater.ng-move { }        
.repeater.ng-move-active { }

and your HTML

<div ng-repeat="..." class="repeater"/>
share|improve this answer
    
Or if you want to animate the div with ng-include you can use the same logic (but only with enter and leave animations) –  NicolasMoise Jan 27 at 15:51
    
Thank you Nicolas. That is what I am using now. My problem is that I want the initial state to depend on the event. So the CSS in ng-enter and ng-leave is different every time the animation starts. Maybe I should have been a bit clearer when explaining my intend.. –  Hendrik Jan Jan 28 at 8:15
add comment
up vote 0 down vote accepted

In the end, I found the following solution:


HTML:
Create an onClick handler and a placeholder where the dialog is loaded.

<!-- Element on which the user clicks to initialize the dialog -->
<div ng-repeat="course in data.courses"
     ng-click="showDialog($event, course)">
 {{ course.name }}
</div>

<!-- Placeholder for blokDialogs -->
<div class="dialogHolder"
     ng-include="dialogTemplate.url"
     onload="showDialogLoaded()">
</div>


HTML Template:
partials/blokDialog.html sets it's style using ng-style.

<div ng-style="dialogTemplate.initialStyle">
...
</div>


Javascript:
The onClick handler sets the initial CSS before the animation starts.

$scope.showDialog = function(evt, course) {

    // Load the dialog template
    $scope.dialogTemplate.url = 'partials/blokDialog.html';

    // set the css before the animation starts
    // get position and size of the course block
    var clientRect = evt.target.getBoundingClientRect();
    $scope.dialogTemplate.initialStyle = {
        left: clientRect.left + 'px',
        top: clientRect.top + 'px',
        width: clientRect.width + 'px',
        height: clientRect.height + 'px',
        backgroundColor: getComputedStyle(evt.target).backgroundColor
    };

};

The style needs to be removed before the animation ends but after the animation started.
The animation starts at the end of the onLoad handler. If we remove the style in the onLoad handler (i.e. in showDialogLoaded), then we are to early.
We use setTimeout to make sure that the removal of the style is done after the animation was started.

$scope.showDialogLoaded = function() {
    // remove the style that we set in showDialog
    setTimeout(function(){
        $scope.dialogTemplate.initialStyle = {};
        // we need to $apply because this function is executed
        // outside normal Angular handling, so Angular does not know
        // that it needs to do a dirty check
        $scope.$apply();
    }, 0);
};

I hope this can be helpful for others.
Regards,
HJ

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.