Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ngAnimate - Sliding both ways

I'm struggling with an issue: I have a menu with x-amount of items. In this example, I have three items.

Each item has a content section, so by clicking on the menu item, the content should slide in.

What I have achieved so far, is that when you're starting from "item 1" and changing to "item 2" will do the animation (sliding from right to left, like a powerpoint slide)

But I'd like the reverse effect as well, so it would slide from right to left when going from "item 2" to "item 1". I just can't figure it out how to do this for both ways.

So what I'm asking for is some kind of carousel with ngAnimate, so I won't have to revert back to jQuery for these kind of animations. I'd like to cut out jQuery from my project while using AngularJS.

console.clear();
var _app = angular.module("animate", ['ngAnimate']);

_app.directive("animate", [function() {
  return {
    scope: {},
    template: '<div class="header">' +
      '		<ul>' +
      '			<li data-ng-repeat="item in items" data-ng-click="move($index)">' +
      '				<div>{{item}}</div>' +
      '			</li>' +
      '		</ul>' +
      '</div>' +
      '<div class="wrapper" style="position: relative; margin-top: 20px;">' +
      '		<div data-ng-if="index == 0" class="slide slide-left">Content 1</div>' +
      '		<div data-ng-if="index == 1" class="slide slide-left">Content 2</div>' +
      '		<div data-ng-if="index == 2" class="slide slide-left">Content 3</div>' +
      '</div>',
    link: function(scope, elem, attr) {
      scope.items = ["Item 1", "Item 2", "Item 3"]
      scope.index = 0;

      scope.move = function(index) {
        scope.index = index;
      }
    }
  }
}]);
body {
  font-family: Arial, Sans-Serif;
}

.header {
  width: 100%;
  height: 50px;
  background-color: lightblue;
  position: relative;
}

.header ul {
  padding: 0;
  height: inherit;
}

.header ul li {
  display: inline;
  width: 33%;
  height: inherit;
}

.header ul li div {
  float: left;
  width: 33%;
  text-align: center;
  height: inherit;
  border: 1px solid black;
}

.slide {
  -webkit-transition: all cubic-bezier(0.250, 0.460, 0.450, 0.940) 2s;
  -moz-transition: all cubic-bezier(0.250, 0.460, 0.450, 0.940) 2s;
  -o-transition: all cubic-bezier(0.250, 0.460, 0.450, 0.940) 2s;
  transition: all cubic-bezier(0.250, 0.460, 0.450, 0.940) 2s;
  position: absolute;
}

.slide-left.ng-enter {
  left: 100%;
}

.slide-left.ng-enter.ng-enter-active {
  left: 0;
}

.slide-left.ng-leave {
  left: 0;
}

.slide-left.ng-leave.ng-leave-active {
  left: -100%;
}

.slide-right.ng-enter {
  left: -100%;
}

.slide-right.ng-enter.ng-enter-active {
  left: 0
}

.slide-right.ng-leave {
  left: 0;
}

.slide-right.ng-leave.ng-leave-active {
  left: 100%;
}
<script src="http://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.8/angular.js"></script>
<script src="https://code.angularjs.org/1.4.8/angular-animate.js"></script>
<div ng-app="animate">
  <animate></animate>
</div>
like image 993
Jorrex Avatar asked Mar 01 '17 21:03

Jorrex


1 Answers

In order to have a carousel effect, you need to switch the slide class based on the index you are transitioning to, so you use ngClass and change the class from slide-left to slide-right when moving to a lower index and vice-versa.

However, for the disappearing element the ngIf hides the element before the class is updated, so you need to delay the transitions to make sure ngClass is executed first. One way to do that is by using the $timeout function, which needs to be injected into your directive.

Your code becomes:

_app.directive("animate", ['$timeout', function($timeout) {
  return {
    scope: {},
    template: '<div class="header">' +
      '     <ul>' +
      '         <li data-ng-repeat="item in items" data-ng-click="move($index)">' +
      '             <div>{{item}}</div>' +
      '         </li>' +
      '     </ul>' +
      '</div>' +
      '<div class="wrapper" style="position: relative; margin-top: 20px;">' +
      '     <div data-ng-if="index == 0" class="slide" ng-class="slideClass">Content 1</div>' +
      '     <div data-ng-if="index == 1" class="slide" ng-class="slideClass">Content 2</div>' +
      '     <div data-ng-if="index == 2" class="slide" ng-class="slideClass">Content 3</div>' +
      '</div>',
    link: function(scope, elem, attr) {
      scope.items = ["Item 1", "Item 2", "Item 3"]
      scope.index = 0;
      scope.slideClass = 'slide-left';

      scope.move = function(index) {
        scope.slideClass = index < scope.index
                         ? scope.slideClass = 'slide-right'
                         : scope.slideClass = 'slide-left';

        $timeout(function() {
          scope.index = index;
        });
      }
    }
  }
}]);

Check this sample.

Also, if you already have UI Bootstrap you might want to try their carousel component.

like image 61
Samir Aguiar Avatar answered Sep 29 '22 12:09

Samir Aguiar