【问题标题】:Angular js - slide views but not home page - ng-animateAngular js - 幻灯片视图但不是主页 - ng-animate
【发布时间】:2014-03-22 22:49:02
【问题描述】:

我正在使用 ng-animate 来滑动应用视图,所以每条路线都会滑动自己的视图,这是我的简单代码:

html:

<div ng-view ng-animate class="slide"></div>

css:

/*Animations*/
.slide{
  left:0;
}
.slide.ng-enter{
  transition:0.15s linear all;
  position:fixed;
  z-index:inherit;
  left:-100%;
  height:inherit;
}
.slide.ng-leave{
  transition:0.15s linear all;
  position:fixed;
  z-index:9999;
  right:0;
}
.slide.ng-leave-active{
  transition:0.15s linear all;
  position:fixed;
  right:-100%;
  left:100%;
}
.slide.ng-enter-active{
  transition:0.15s linear all;
  left:0;
  position:relative;
}

现在,我想知道,is there anyway to exclude the home page (main "/" route) from sliding?

换句话说:有什么方法可以从 ng-animate 中排除路由?

【问题讨论】:

  • 你能解决这个问题吗?
  • @PavelNikolov nope 仍在寻找好的解决方案
  • 我不认为ng-animate 会在这里做任何事情,官方文档中没有关于ng-animate 指令的信息。我还更新了我的答案以反映来自@sbaaaang 的最新请求。
  • 嘿,对不起,我真的是 Angular 的新手,我的问题是寻求一个最佳实践,我给你们所有人 +1,但我在接受哪个答案时遇到了麻烦,因为 IMO 这些是所有好的解决方案

标签: javascript css angularjs slide ng-animate


【解决方案1】:

这就是ng-class 的用途。

您可以在路径更改时设置应用程序范围的变量 $rootScope.path。

app.run(function ($rootScope, $location) {
  $rootScope.$on("$locationChangeStart", function (event, next, current) {
    $rootScope.path = $location.path();
  });
});

然后,您决定通过该变量设置动画类

如果你想设置类slide只有当路径不是/时,这样做

<div ng-view ng-class="{slide: path !== '/' }"></div>

通过这种方式,您无需触摸任何控制器。

完整的演示在这里,http://plnkr.co/edit/rmu8oc7ycKzRaA2zv5JN?p=preview

顺便说一下,这里使用的是 currant angularJS 版本,1.2.7

------- 编辑(访问主页后动画)------

app.run(function ($rootScope, $location) {
  $rootScope.$on("$locationChangeStart", function (event, next, current) {
    if (!$location.path().match(/^\/?$/) && !$rootScope.mainVisitedOnce) {
      $rootScope.mainVisitedOnce = true;
    }
  });
});

<div ng-view ng-class="{slide: mainVisitedOnce }"></div>

http://plnkr.co/edit/QpDFkdKH1kk6ZXy07G5X?p=preview

【讨论】:

  • 我真的很喜欢你的解决方案,只是你认为有可能做到完全相同的事情,但只在第一次加载应用程序时?我的意思是只有 1 次,只有当应用程序第一次打开时...
  • 是的,但这不是您的问题的一部分,在应用加载时不要滑动
  • 我将答案编辑为在应用加载时不设置动画。因此,请相应地编辑您的问题,以便观众可以看到答案正在关注您的问题。
  • 嘿,对不起,我真的是 Angular 的新手,我的问题是寻求一个最佳实践,我给你们所有人 +1,但我在接受哪个答案时遇到了麻烦,因为 IMO 这些是所有好的解决方案
【解决方案2】:

演示http://plnkr.co/edit/sMUM48?p=preview

解释

无需创建单独的控制器、指令或更改任何业务逻辑。只需使用.animation 方法将条件动画添加到.slide

$rootScope 上收听$routeChangeSuccess 事件。这是在动画开始之前触发的事件,因此您有时间相应地设置toRootfromRoot 标志。如果目标视图不是 "/" 视图,则会在 ng-view 元素中添加一个 enable-animation 类,因此将执行定义的 css 转换。

如果目标视图是 "/" 视图,则不会执行动画。

HTML

<ng-view class="slide"></ng-view>

CSS

.slide {
  position: absolute;
  top: 0;
  width: 100%;
}
.slide div {
  margin: 10px;
  background: red;
}

.slide.enable-animation.ng-enter,
.slide.enable-animation.ng-leave {
  transition: all 10s;
  z-index: 1;
}

.slide.enable-animation.ng-enter {
  left: -100%;
  opacity: 0;
}

.slide.enable-animation.ng-enter.ng-enter-active,
.slide.enable-animation.ng-leave {
  left: 0;
  opacity: 1;
}

.slide.enable-animation.ng-leave.ng-leave-active {
  left: 100%;
  opacity: 0;
}

JavaScript

app.animation('.slide', function($rootScope, $animate) {

  var toRoot = false;
  var fromRoot = false;

  $rootScope.$on('$routeChangeSuccess', function(event, current, old) {
    toRoot = (current.$$route.originalPath === '/');
    fromRoot = (old.$$route.originalPath === '/');
  });

  return {
    enter: function(element, done) {
      if (!toRoot) {
        element.addClass('enable-animation');
      }
      done();
    },

    leave: function(element, done) {
      if (!fromRoot) {
        element.addClass('enable-animation');
        done();
      } else {
        // set 1000ms timeout to sync with CSS animation
        // otherwise leaving ng-view element will be removed before entering ng-view is in position
        setTimeout(done, 1000);
      }
    }
  }
});

更新 1

如果您只想在第一次加载应用程序时排除路由,您基本上不需要做任何事情,只需像平常一样定义您的 css 动画。第一个加载的路由不会触发任何动画。

演示http://plnkr.co/edit/uRZyZA?p=preview

【讨论】:

  • 嘿,对不起,我真的是 Angular 的新手,我的问题是寻求一个最佳实践,我给你们所有人 +1,但我在接受哪个答案时遇到了麻烦,因为 IMO 这些是所有好的解决方案
【解决方案3】:

从 @allenhwkim 借用,在你的 rootScope 中获取路径。

app.run(function ($rootScope, $location) {
  $rootScope.$on("$locationChangeStart", function (event, next, current) {
    $rootScope.path = $location.path();
  });
});

然后将其作为您的元素:

<div ng-view ng-animate ng-class="{slide: path !== '/' }"></div>

.slide 将在加载路径时添加到您的容器元素中不是 /

Here's a working Plunker.

【讨论】:

  • 你能提供一个有效的plnkr吗,因为我在官方文档中没有看到ng-animate指令。
  • 我在写我的答案时似乎一直在考虑 Angular 1.1.X — 一个错误。我已经更新了我的答案以适应 Angular 1.2.9。
  • 由于我的解决方案涉及 @allenhwkim 最初所做的事情,我赞成他的回答。
  • 嘿,对不起,我真的是 Angular 的新手,我的问题是寻求一个最佳实践,我给你们所有人 +1,但我在接受哪个答案时遇到了麻烦,因为 IMO 这些是所有好的解决方案
  • 我认为应该交给 allenhwkim,因为我的解决方案最终是他最初发布的解决方案,我认为这是最优雅的。
【解决方案4】:

您为什么不简单地将像 class="not-animated"class="animated" 这样的根类添加到您不想或想要动画的控制器中?
通过这种方式,您可以使用.not-animated.animated 类在不同的控制器中播放动画。

你可以这样设置你的控制器:

<body ng-controller="MainCtrl" ng-class='isAnimated'>
  <div ng-controller="FirstCtrl" ng-class='isAnimated'>Foo</div>
  <div ng-controller="SecondCtrl" ng-class='isAnimated'>Bar</div>
</body>

app.controller('MainCtrl', function($scope) {
  $scope.name = 'World';
  $scope.isAnimated = 'not-animated';
});

app.controller('SecondCtrl', function($scope) {
  $scope.isAnimated = 'animated';
});  

这将导致:

<body ng-controller="MainCtrl" ng-class="isAnimated" class="ng-scope not-animated">
    <p class="ng-binding">Hello World!</p>
    <div ng-controller="FirstCtrl" ng-class="isAnimated" class="ng-scope not-animated">Foo</div>
    <div ng-controller="SecondCtrl" ng-class="isAnimated" class="ng-scope animated">Bar</div>   
</body>

DEMO

【讨论】:

  • 你的意思是为主要的动画 div 创建一个 crontoller?
  • 我设置了一个快速插件来演示我的意思。当然你不需要到处都应用它,你可以在你需要的地方设置它。
  • 你可以在添加动画时添加 ng-class,但可能会有点冗长。
  • 嘿,抱歉,我真的是 Angular 的新手,我的问题是寻求最佳实践,我给你们所有人 +1,但我在接受哪个答案时遇到了麻烦,因为 IMO 这些是所有好的解决方案
【解决方案5】:

您可以构建一个控制器来监听路由变化并相应地设置一个类。然后,您将能够使用 CSS 定位正确的动画。

<body ng-controller="TranisitionCtrl" ng-class="currentRoute">
  <div ng-view ng-animate></div>
</body>

app.controller('TranisitionCtrl', function($scope) {
  $scope.$on('$routeChangeStart', function(ev, next, current) { 
    $scope.currentRoute = current.name;
  });
}); 

请注意 $routeChangeStart 已更改为 $locationChangeStart 以获取更新版本的 angular。

我在这里Two different animations for route changes回答了另一个类似的问题

【讨论】:

  • 嘿,对不起,我真的是 Angular 的新手,我的问题是寻求一个最佳实践,我给你们所有人 +1,但我在接受哪个答案时遇到了麻烦,因为 IMO 这些是所有好的解决方案
  • 您能否详细说明在最近的 Angular 中将 $routeChangeStart 更改为 $locationChangeStart?我的印象是它们处理逻辑的不同部分 - 位置事件被触发以更改 URL,而路由事件则基于该位置用于不同视图,尽管它们不一定在所有情况下都包含在内。
【解决方案6】:

从动画中排除特定路线的一种方法是使用 JS 动画包装器,它将接管您的 ng-view 的动画类设置。当您返回非动画路线时,您需要一个额外的类来处理非动画ng-leave

这是一个示例 JS 包装器,它检查您的路线中的自定义 animate 属性以确定路线是否为动画:

app.animation('.slider', function($log, $route) {
  return {
    //call done when the animation is over
    enter : function(element, done) {
      if ($route.current.animate) {
        element.addClass("slide ng-enter");
      }
      done();
    },
    leave : function(element, done) {
      if ($route.current.animate) {
        element.addClass("slide ng-leave");
      } else {
        // Need to add non-animated version of ng-leave
        element.addClass("slide ng-leave-noanimation");
      }
      done();
    }
  }
});

这里是工作插件:
http://plnkr.co/edit/ldCy9Cfz2lJWNuLzDIbp?p=preview

【讨论】:

  • 嘿,对不起,我真的是 Angular 的新手,我的问题是寻求一个最佳实践,我给你们所有人 +1,但我在接受哪个答案时遇到了麻烦,因为 IMO 这些是所有好的解决方案
【解决方案7】:

据我了解,您想要的是,如果用户点击您的网站,则不会发生动画。但在那之后,动画应该一直发生。这是我所知道的最短解决方案:

使用模块run方法禁用所有动画:

app.run(function($animate){
    $animate.enabled(false);
});

在绑定到/ 的控制器中重新启用动画,但延迟一个摘要周期:

.controller('rootController', function($timeout, $animate){
    $timeout(function(){
        $animate.enabled(true);
    });
})

【讨论】:

  • 嘿,对不起,我真的是 Angular 的新手,我的问题是寻求一个最佳实践,我给你们所有人 +1,但我在接受哪个答案时遇到了麻烦,因为 IMO 这些是所有好的解决方案
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-12-05
  • 2018-03-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-05-12
相关资源
最近更新 更多