Search code examples
angularjscss-animationsangularjs-animation

AngularJS animation timing issue


I 'm building an application with a number of slides, and I'm using Angular JS to toggle classes on the elements that trigger CSS animations. The problem that I'm having is that when a button is clicked that triggers a function on the angular controller that updates the $scope's property that determines the element's class, the property that causes the animation to begin appears to be updated before the element's old class is removed, and the new class assigned, so the element always moves in only one direction.

What I want to happen is when the proceed() function gets called from slide1, for slide2 to slide in from the right to the left, which it does correctly, but when the backToOne function gets called by clicking the Back button on slide 2, slide2 should slide out to the right.

What's actually happening is that when the backToOne() function gets called, slide2 slides out to the left. Any help is appreciated. I'm pretty new to angular, so I'm trying to figure out what I need to do to update that class, and then change the property's value that causes the animation to happen.

Thanks in advance.

Here's the (simplified) view:

<div ng-init="switcher='one'">
    <div ng-switch="switcher" class="my-switch-container">
      <div ng-switch-when="one" id="slide1" ng-class="slide1">
        <p>stuff</p>
        <button type="button" class="btn btn-primary" ng-click="proceed()">Proceed</button>
      </div>
      <div ng-switch-when="two" id=slide2" ng-class="slide2">
        <p>more stuff</p>
        <button type="button" class="btn" ng-click="backToOne()">Back</button>
        <button type="button" class="btn btn-primary" ng-click="keepGoing()">Go</button>
      </div>
      <div ng-switch-when="three" id=slide3" ng-class="slide3">
        <p>last stuff</p>
      </div>
    </div>
  </div>

Here's the (again, simplified) controller:

myApp.controller('siteCtrl', ['$scope', '$http', 'SomeData', function($scope, $http, SomeData) {
    $scope.model = SomeData;
    $scope.animateLeft = "my-switch-animation-left";
    $scope.animateRight = "my-switch-animation-right";
    $scope.slide1 = $scope.animateLeft;
    $scope.slide2 = $scope.animateLeft;
    $scope.slide3 = $scope.animateLeft;

    $scope.proceed = function() {
      $scope.switcher = "two";
      $scope.slide1 = $scope.animateRight;
    }

    $scope.backToOne = function() {
      $scope.slide2 = $scope.animateRight;
      $scope.switcher = "one";
    }

    $scope.keepGoing = function() {
      $scope.switcher = "three";
      $scope.slide2 = $scope.animateRight;
    }
}]);

Here's the CSS:

.my-switch-container{
    position: relative;
}

.my-switch-animation-left, .my-switch-animation-right {
    width: 700px;
    background-color: #FFF;
    border-radius: 20px;
    border: 1px solid #000;
    -webkit-border-radius: 20px;
    -moz-border-radius: 20px;
    -webkit-box-shadow: 0 5px 15px #000;
    -moz-box-shadow: 0 5px 15px #000;
    -ms-box-shadow: 0 5px 15px #000;
    box-shadow: 0 5px 15px #000;
    margin: 0 auto;
}
.my-switch-animation-left.ng-enter, 
.my-switch-animation-left.ng-leave, 
.my-switch-animation-right.ng-enter, 
.my-switch-animation-right.ng-leave {
    -webkit-transition: 1s linear all;
    -moz-transition: 1s linear all;
    -o-transition: 1s linear all;
    -transition: 1s linear all;
    position: relative;
    top: 0px;
}
/* moving right to left */
.my-switch-animation-left.ng-enter{
    left: 100%;
}
.my-switch-animation-left.ng-leave, 
.my-switch-animation-left.ng-enter.ng-enter-active{
    left: 0;
}
.my-switch-animation-left.ng-leave.ng-leave-active{
    left: -100%;
}
/* moving left to right */
.my-switch-animation-right.ng-enter{
    right: 100%;
}
.my-switch-animation-right.ng-leave, 
.my-switch-animation-right.ng-enter.ng-enter-active{
    right: 0;
}
.my-switch-animation-right.ng-leave.ng-leave-active{
    right: -100%;
}

Here's a (gross) plunkr of it: http://plnkr.co/edit/hSUEQDkVMSdwX2nPEFly?p=info


Solution

  • try this:

    $scope.backToOne = function() {
      $scope.slide2 = $scope.animateRight;
      $scope.$apply();
      $scope.switcher = "one";
    }
    

    The digest didn't have a chance to run before applying the ng-class. $apply will force the scope to reevaluate. There's an error that pops up on the console, but it works.