【问题标题】:Slide up/down effect with ng-show and ng-animate使用 ng-show 和 ng-animate 实现上/下滑动效果
【发布时间】:2013-05-16 15:37:38
【问题描述】:

我正在尝试使用 ng-animate 来获得类似于 JQuery 的 slideUp()slideDown() 的行为。只有我宁愿使用ng-show

我在这里查看 ng-animate 教程 - http://www.yearofmoo.com/2013/04/animation-in-angularjs.html

我可以在提供的示例中重现淡入/淡出效果。

如何更改 css 以获得向上/向下滑动的行为? 此外,如果可能,最好让 css 不知道组件高度(以像素为单位)。 这样我就可以将 css 重用于不同的元素。

【问题讨论】:

  • 我认为你不能让 ng-show 来处理动画。那不是它的预期用途。这就是 ng-animate 的用途。为什么要专门使用 ng-show?
  • 谢谢乔纳森。我认为你错了。给定的示例正是这样做的:ng-show 和 ng-animate 的组合(查找“Animating ngShow & ngHide”)。无论如何,我想要的只是显示/隐藏上下滑动的 div 的效果。
  • 我的错,我没有使用 ng-animate。看起来它们似乎相互配合。
  • 您可以尝试使用line-height css 属性,从 0 到 100%。有时它是有效的......发布你的小提琴比我们可以更好地帮助你。如果你找到了一个好的方法,请发给我,把这个样本放在我的网站上:AngularJS Ng-Animate
  • 看看这个nganimate.org

标签: css angularjs


【解决方案1】:

我编写了一个 Angular 指令,它在没有 jQuery 的情况下执行 slideToggle()

https://github.com/EricWVGG/AngularSlideables

【讨论】:

  • 这看起来和我想要的完全一样。谢谢!
  • @BastienSander Angular 提供了一些 Jquery 方法的子集,如果您在包含 Angular 之前不包含 jquery,此处提供了 api 文档:docs.angularjs.org/api/ng/function/angular.element .css 和 .bind 在那里提供(其中用于“元素”变量)。缓动和持续时间属性没有在元素上使用,因此它们没有引用同名的 Jquery 方法,而是在 HTML 属性(attrs 对象)上传递的属性。
  • 我见过的最小的“手风琴”风格滑块!谢谢!我们对其进行了一些修改,以删除我们认为不必要的 ID 和类内容,因为我们可以找到没有 ID 的元素:plnkr.co/edit/11NIZqB3G3KYKI0OChGA?p=preview
  • id 有点需要(如果你想下拉其他地方的元素),所以我做了一些修改,修复了一些错误,现在它就像一个魅力。 plnkr.co/edit/XdRjap3TPFEC9180yq9k?p=preview
  • 我知道我们已经把它搞砸了,但我喜欢将可见性与变量联系起来。此外,此解决方案不允许嵌入滑块。我创建了一个既可以做到的小提琴:jsfiddle.net/rh7z7w0a/2
【解决方案2】:

这实际上很容易做到。您所要做的就是更改 css。

这是一个非常简单的淡入淡出动画:http://jsfiddle.net/elthrasher/sNpjH/

为了让它变成一个滑动动画,我首先必须把我的元素放在一个盒子里(那是滑动容器),然后我添加了另一个元素来替换那个离开的元素,只是因为我觉得它看起来不错.取出它,示例仍然有效。

我将动画 css 从 'fade' 更改为 'slide' 但请注意这些是我给它起的名字。我本可以编写名为“fade”的幻灯片动画 css 或其他任何东西。

重要的部分是 css 中的内容。这是原始的“淡入淡出”css:

.fade-hide, .fade-show {
    -webkit-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;
    -moz-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;
    -o-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;
    transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;
}
.fade-hide {
    opacity:1;
}
.fade-hide.fade-hide-active {
    opacity:0;
}
.fade-show {
    opacity:0;
}
.fade-show.fade-show-active {
    opacity:1;
}

此代码将元素的不透明度从 0(完全透明)更改为 1(完全不透明),然后再变回来。解决方案是单独保留不透明度,而是更改顶部(或左侧,如果您想左右移动)。

.slide-hide, .slide-show {
    -webkit-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 1.5s;
    -moz-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 1.5s;
    -o-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 1.5s;
    transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 1.5s;
}
.slide-hide {
    position: relative;
    top: 0;
}
.slide-hide.slide-hide-active {
    position: absolute;
    top: -100px;
}
.slide-show {
    position: absolute;
    top: 100px;
}
.slide-show.slide-show-active {
    position: relative;
    top: 0px;
}

我也在从相对定位更改为绝对定位,因此一次只有一个元素占用容器中的空间。

这是成品:http://jsfiddle.net/elthrasher/Uz2Dk/。希望这会有所帮助!

【讨论】:

  • 这很有帮助。我试图弄清楚为什么“隐藏”过渡在你的小提琴中如此突然,@elthrasher
  • @ericpeters0n - 这是因为过渡线末端的 0.5 秒。这就是它需要的时间,在这种情况下是半秒。您可以将其设置为您喜欢的任何内容。试试 5s 或 10s。
  • 这种行为有点奇怪。有时文本从顶部显示,有时从底部显示。
  • 我知道这是一个旧答案,但如果有人想尝试一下,我想澄清一下使用ng-hide="hidden == false" 是多余的,如果hidden 变量已经是布尔值,那么运算符根本不需要。
【解决方案3】:

Angular 1.2+ 更新(发文时为 v1.2.6):

.stuff-to-show {
  position: relative;
  height: 100px;
  -webkit-transition: top linear 1.5s;
  transition: top linear 1.5s;
  top: 0;
}
.stuff-to-show.ng-hide {
  top: -100px;
}
.stuff-to-show.ng-hide-add,
.stuff-to-show.ng-hide-remove {
  display: block!important;
}

(plunker)

【讨论】:

  • 不要用css动画顶部位置,它很慢并且占用大量内存。请改用翻译。
  • 也适用于 Angular 1.4。经过测试,它就像一个魅力!
【解决方案4】:

实际上可以在 CSS 和非常小的 JS 中完成,只需添加一个 CSS 类(不要直接在 JS 中设置样式!),例如ng-click事件。原则是不能将height: 0; 动画化为height: auto;,但这可以通过动画max-height 属性来欺骗。当设置.foo-open 时,容器将扩展到它的“自动高度”值 - 无需固定高度或定位。

.foo {
    max-height: 0;
}

.foo--open {
    max-height: 1000px; /* some arbitrary big value */
    transition: ...
}

this fiddle by the excellent Lea Verou

作为 cmets 中提出的一个问题,请注意,虽然此动画与线性缓动完美配合,但任何指数缓动都会产生与预期不同的行为 - 因为动画属性是 max-height 而不是height 本身;具体来说,只会显示max-height 的缓动曲线的height 部分。

【讨论】:

  • 这很糟糕,因为动画速度会根据max-height而变化。
  • 为什么它不好?如果您对动画速度有疑问,只需根据您的max-height 将过渡持续时间设置为合理的值。这正是转换应该如何工作的。这种方法实际上的好处是无论height
  • @RushPL 这是一个公平的解释——现在说得通了。
  • 我必须对这种方法进行投票。简单,以及使用 ngAnimate 框架。
  • 这应该被标记为答案,因为我被带到这里寻找一种欺骗高度的方法:像原始海报一样的汽车
【解决方案5】:

我最终放弃了我的other answer 的代码来回答这个问题,而是选择了这个答案。

我认为最好的方法是完全不使用ng-showng-animate

/* Executes jQuery slideDown and slideUp based on value of toggle-slidedown 
   attribute.  Set duration using slidedown-duration attribute.  Add the 
   toggle-required attribute to all contained form controls which are
   input, select, or textarea.  Defaults to hidden (up) if not specified
   in slidedown-init attribute.  */
fboApp.directive('toggleSlidedown', function(){
    return {
        restrict: 'A',
        link: function (scope, elem, attrs, ctrl) {
            if ('down' == attrs.slidedownInit){
                elem.css('display', '');
            } else {
                elem.css('display', 'none');
            }
            scope.$watch(attrs.toggleSlidedown, function (val) {
                var duration = _.isUndefined(attrs.slidedownDuration) ? 150 : attrs.slidedownDuration;
                if (val) {
                    elem.slideDown(duration);
                } else {
                    elem.slideUp(duration);
                }
            });
        }
    }
});

【讨论】:

  • 感谢您提供更新的解决方案。出于好奇(因为我没有发现搭载 ng-hide/ng-show 的任何特殊问题)......这种方法有什么问题?
  • 您应该修改以前的答案,而不是创建一个新答案(想象一下,如果每个人每次想要修改某些内容时都创建一个新答案,那会是一团糟……)
  • @tanguy_k 我认为可能有一种方法可以纠正第一个答案,并且可能两种方法都有效。我想我希望有人会批评我的第一个答案并告诉我为什么它偶尔会失败。我认为这个问题可能有多个同样好的答案。
  • 编辑原始答案的问题是,如果提问者将其标记为“正确”,然后您制作了重要的模组......这似乎也是一个坏主意。
【解决方案6】:

这个基于类的 javascript 动画在 AngularJS 1.2(和 1.4 测试)中工作

编辑:我最终放弃了这段代码,走向了完全不同的方向。我喜欢my other answer much better。这个答案会在某些情况下给你带来一些问题。

myApp.animation('.ng-show-toggle-slidedown', function(){
  return {
    beforeAddClass : function(element, className, done){
        if (className == 'ng-hide'){
            $(element).slideUp({duration: 400}, done);
        } else {done();}
    },
    beforeRemoveClass :  function(element, className, done){
        if (className == 'ng-hide'){
            $(element).css({display:'none'});
            $(element).slideDown({duration: 400}, done);
        } else {done();}
    }
}

});

只需将.ng-hide-toggle-slidedown类添加到容器元素中,jQuery的滑下行为就会基于ng-hide类实现。

您必须在beforeRemoveClass 方法中包含$(element).css({display:'none'}) 行,因为除非元素在开始jQuery 动画之前处于display: none 状态,否则jQuery 不会执行slideDown。 AngularJS 使用 CSS

.ng-hide:not(.ng-hide-animate) {
    display: none !important;
}

隐藏元素。 jQuery 不知道这种状态,jQuery 在第一个向下滑动动画之前需要display:none

AngularJS 动画将在动画发生时添加.ng-hide-animate.ng-animate 类。

【讨论】:

  • 这对我来说非常有效,而我无法获得其他适合我的答案。投票赞成!
  • @zaichang 我最终放弃了这段代码并走向了完全不同的方向。我喜欢我的other answer much better。这个答案会在某些情况下给你带来一些问题。
  • @steampowered 这将/不能与ngIf 一起使用。但我也看到即使您使用ngShow,它在某些情况下也不起作用。例如。当我在使用 UI-Bootstrap 创建的模式中使用它时,它似乎不起作用。这很奇怪。你什么时候失败了?
  • 显示:无所事事...使用带有进入/离开功能和 jquery UI 切换效果的 ng-animate/ng-show。在我将 display:none 添加到元素之前,Nothign 一直正常工作......谢谢!
【解决方案7】:

您应该为此使用 Javascript 动画 - 这在纯 CSS 中是不可能的,因为您无法知道任何元素的高度。按照它为您提供的有关 javascript 动画实现的说明,并从 jQuery 的源代码复制 slideUp 和 slideDown。

【讨论】:

    【解决方案8】:

    你提到的ng-show 实际使用ng-animate 有什么问题?

    <script src="lib/angulr.js"></script>
    <script src="lib/angulr_animate.js"></script>
    <script>
        var app=angular.module('ang_app', ['ngAnimate']);
        app.controller('ang_control01_main', function($scope) {
    
        });
    </script>
    <style>
        #myDiv {
            transition: .5s;
            background-color: lightblue;
            height: 100px;
        }
        #myDiv.ng-hide {
            height: 0;
        }
    </style>
    <body ng-app="ang_app" ng-controller="ang_control01_main">
        <input type="checkbox" ng-model="myCheck">
        <div id="myDiv" ng-show="myCheck"></div>
    </body>
    

    【讨论】:

    • 如果您可以在 CSS 中对高度进行硬编码,它就可以工作,但这通常是不可能的。
    猜你喜欢
    • 2013-03-29
    • 1970-01-01
    • 2014-04-27
    • 2014-07-24
    • 1970-01-01
    • 2014-12-02
    • 1970-01-01
    • 2016-04-24
    • 2019-12-13
    相关资源
    最近更新 更多