给angular的repeat列表的行操纵加上动效碰到的题目总结

到场“动效”是让用户对运用的行动举行感知的一种有用手腕。“列表”是运用中最常运用的一种界面情势,常常会有增加行,删除行,挪动行这些操纵。想象增加的操纵很简朴,删除时从大到小,然后消逝;增加时从小到大;挪动就是先删除再增加。以为上并不庞杂,应当应用CSS的transition就能够搞定,然则现实做起来发现有不少题目要处置惩罚,下面一一道来。

来些简朴的测试

1、最初的版本

<div class='list'>
    <div class='row-1'>row-1</div>
    <div class='row-2'>row-2</div>
</div>
.list{margin:20px;background:#eee;font-size:18px;color:white;}
.row-1{background:green;overflow:hidden;padding:15px;}
.row-2{background:blue;padding:15px;}
/*demo1*/
.demo-1 .remove{-webkit-transition: height 3s linear;}
.demo-1 .remove.active{height:0;}
var ele = document.querySelector('.demo-1 .row-1');
ele.classList.add('remove');
ele.classList.add('active');

主意很简朴,经由历程增加“remove”类,设置动画的效果,增加“active”修正css属性,激活动画。

《给angular的repeat列表的行操纵加上动效碰到的题目总结》

效果和想的不一样,两个题目:1、动画并没有运转;2、row-1并没有消逝。为何?起首,CSS的transition不能作用于auto的属性,由于row-1原本并没有设置height,所以不会发生从现有的高度变到0的动画。第二,height=0只是设置了content地区为0,padding并没有转变,所以照样row-1照样占有了30px的空间。

2、指定牢固的height而且padding也加上动画

调解CSS

/*demo2*/
.demo-2 .row-1{height:48px;}
.demo-2 .remove{-webkit-transition: height 3s linear, padding-top 3s linear;}
.demo-2 .row-1.remove.active{height:0;padding-top:0;padding-bottom:0;}

《给angular的repeat列表的行操纵加上动效碰到的题目总结》

此次的效果是对的,row-1从48px边到0,同时padding也随着变。

3、另有没有别的要领呢?一定要指定height吗?transform行不行

修正CSS

/*demo3*/
.demo-3 .remove{-webkit-transition: -webkit-transform 3s linear,padding 0s linear 3s;}
.demo-3 .row-1.remove.active{-webkit-transform-origin:0 0;-webkit-transform:scaleY(0);}

《给angular的repeat列表的行操纵加上动效碰到的题目总结》
纵然没有设置height,经由历程transform实行动画也是没有题目的。题目是,row-1还在本来的处所,还占着空间,row-2并没有向上挪。由此带来个题目,动画实行完了(包含第2个设置height的例子),row-1并没有删撤除,只是看不见了。

4、处理动画实行完消灭元素的题目

修正CSS

.demo-4 .remove{-webkit-transition: height 3s linear, padding 3s linear, opacity 3s linear,color .5s linear;}
.demo-4 .row-1.remove.active{padding-top:0;padding-bottom:0;color:rgba(0,0,0,0);opacity:0;}

修正JS

var ele, l;
ele =  document.querySelector('.demo-4 .row-1');
l = ele.addEventListener('webkitTransitionEnd', function(evt){
    if (evt.propertyName === 'height') {
        ele.style.display = 'none';     
        ele.style.height = '';
        ele.removeEventListener('webkitTransitionEnd', l, false);
    }
}, false);
ele.style.height = ele.offsetHeight + 'px';
ele.classList.add('remove');
$timeout(function(){
    ele.classList.add('active');
    ele.style.height = '0px';
});

《给angular的repeat列表的行操纵加上动效碰到的题目总结》

此次的效果不错。有几个注重的处所:1、经由历程注册transitionEnd事宜能够捕获到动完毕;2、能够同时实行多个动效,每一个东西完毕都邑发生transitionEnd事宜,经由历程事宜的“propertyName”能够晓得是哪一个属性的动效完毕了。

5、用velocity.js也试了一下

CSS不必设置
JS代码

var ele =  document.querySelector('.demo-5 .row-1');
Velocity(ele, 'slideUp', { duration: 1000 });   

《给angular的repeat列表的行操纵加上动效碰到的题目总结》

看了看实行的历程,也是修正height和padding。然则,velocity用的是requestAnimationFrame函数。我以为假如动效比较简朴,就不必引入其他的库了,直接写出来的运转效果差不多。

6、高度搞邃晓了,变宽度呢?

调解CSS

.demo-6 .row-1{width:100%;}
.demo-6 .remove{-webkit-transition: width 3s linear;}
.demo-6 .row-1.remove.active{width:0%;}

《给angular的repeat列表的行操纵加上动效碰到的题目总结》

虽然宽自身能够经由历程百分比举行设置,然则height不牢固的题目照样存在。

7、用上JS处理变width的题目

设置CSS

.demo-7 .row-1{width:100%;height:48px;}
.demo-7 .remove{-webkit-transition: width 3s linear, opacity 3s ease;}
.demo-7 .row-1.remove.active{width:0%;opacity:0;}

《给angular的repeat列表的行操纵加上动效碰到的题目总结》

牢固了height已有动效一般了。其他的革新可参照前面的例子了。

二、一个完全的例子

完全的例子着实angular中完成的。angular完成起首一个题目就是在什么机遇设置动效?由于,angular是双向绑定的,假如在controller中删除了一个对象,衬着界面的时刻这个对象就没了,所以必需参与到数据绑定的历程当中。angular供应ngAnimatie这个动画模块,试了一下它也确切能够完成ngRepeat列表数据更新的动效。然则要分外引入angular-animation.js,虽然不大,照样以为不是很有必要。别的,我是在一个已写好的框架页面上加动画,假如须要引入新的module,须要改框架文件,我以为不好。试了试动态加载animation模块也没胜利,所以就研讨了一下本身怎样掌握动效。

angular纵然不加载animation模块,也有一个$animate,它为动效掌握留出了接口。
看JS

var fnEnter = $animate.enter,
    fnLeave = $animate.leave;
$animate.enter = function() {
    var defer = $q.defer(),
        e = arguments[0],
        p = arguments[1],
        a = arguments[2],
        options = {
            addClass: 'ng-enter'
        };
    fnEnter.call($animate, e, p, a, options).then(function() {
        $animate.addClass(e, 'ng-enter-active').then(function(){
            var l = e[0].addEventListener('webkitTransitionEnd', function(){
                e[0].classList.remove('ng-enter-active');
                e[0].classList.remove('ng-enter');
                e[0].removeEventListener('webkitTransitionEnd', l, false);
                defer.resolve();
            }, false); 
        });
    });
    return defer.promise;
};
$animate.leave = function() {
    var defer = $q.defer(),
        e = arguments[0];
    $animate.addClass(e, 'ng-leave').then(function(){
        $animate.addClass(e, 'ng-leave-active').then(function(){
            var l = e[0].addEventListener('webkitTransitionEnd', function(){
                fnLeave.call($animate, e).then(function(){
                    defer.resolve();
                });
            }, false);
        });
    });
    return defer.promise;
};

ng-repeat举行数据更新是会挪用$animate效劳的enters,leave和move要领,所以,要本身掌握动效就要重写对应的要领。重写的时刻要用$animate增加,直接在dom上设置有题目。(这一段的angular的逻辑比较底层,没有太看邃晓,还须要深入研讨。)

别的,在挪动行的位置时,要经由历程$timeout将删除和插进去放到两个digest轮回中处置惩罚,不然看不出效果。

var index = records.indexOf($scope.selected),
    r = records.splice(index, 1);
$timeout(function(){
    records.splice(index + 1, 0, r[0]);
},500);

angular的动画和digest轮回关系密切,看了angular-animation.js的代码没看邃晓,还须要深入研讨才行。

示例

基本的示例
完全示例

    原文作者:游于藩篱
    原文地址: https://segmentfault.com/a/1190000004436809
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞