美文网首页
css3动画transition transform性能对比及原

css3动画transition transform性能对比及原

作者: 宋乐怡 | 来源:发表于2020-05-14 01:02 被阅读0次

    本文你将看到:

    1. Vue页面初始化加载进度条动画:animation方式
    2. transition ,transform, translate三者的用法(一年之内不写就忘)
    3. 动画性能对比

    1. Vue页面初始化加载进度条动画 :animation方式

    场景:
    今天要写一个进度条动画,但是我平时写简单的动效都是用transition+transform的方式,已经习惯了,但这个动画的场景是页面一载入就执行,transition的方式的话,常用方式总是需要hover或者一些动作才能触发。所以我选择了animation,以为很简单,但实际写起来没想到真的很简单。印象中有动画性能比较这件事,所以我又学了点东西,后续有写到。

    效果:
    进入页面时播放动画,浮标从头移动,停在指定位置。我不方便录屏。

    image.png

    思路:

    1. 元素分为两部分:浮标buoy和进度条bar

    2. 页面挂载完成mounted时执行函数,为元素添加动画类。
      此处注意ref虽然一直存在,但是在created阶段并没有挂载完成,ref是空对象,因此在mounted阶段取值,nextTick方式也可以。

    3. 进度条bar思路相同,只不过如图,灰色底色不动,上层黄色用遮罩方式,执行动画。

    4. animation还有许多属性,可以做复杂的动画,可以自己去学习。

    HTML

    <!--动画进度条-->
                <div class="bar-wrapper">
                    <!--浮标-->
                    <img ref="buoy"
                         src="http://p0.meituan.net/scarlett/127d53efa1189f26053b702c15771db4547.png"
                         alt
                         class="buoy"/>
                    <!--进度条-->
                    <div class="bar">
                        <span v-if="grade <= 35" class="text text-mid">中</span>
                        <span v-if="grade <= 65" class="text text-high">高</span>
                        <!--黄色条-->
                        <div ref="bar" class="bar-yellow-modal">
                            <span class="text-in-yellow yellow-low">低</span>
                            <span v-if="grade > 35" class="text-in-yellow yellow-mid">中</span>
                            <span v-if="grade > 65" class="text-in-yellow yellow-high">高</span>
                        </div>
                    </div>
                </div>
    

    JS

          mounted() {
                // 执行进度条动画
                this.animation();
            },
    
            methods: {
                animation() {
                    if (this.$refs && this.$refs.buoy && this.$refs.bar) {
                        let elBuoy = this.$refs.buoy;
                        let elBar = this.$refs.bar
                        console.log(this.$refs)
                        if (this.grade && this.grade > 0) {
                            switch (true) {
                                case 0 < this.grade && this.grade <= 35 :
                                    elBuoy.className = 'buoy buoy-moving-step-1';
                                    elBar.className = 'bar-yellow-modal bar-step-1';
                                    break;
                                case 35 < this.grade && this.grade <= 65 :
                                    elBuoy.className = 'buoy buoy-moving-step-2';
                                    elBar.className = 'bar-yellow-modal bar-step-2';
                                    break;
                                case 65 < this.grade :
                                    elBuoy.className = 'buoy buoy-moving-step-3';
                                    elBar.className = 'bar-yellow-modal bar-step-3';
                                    break;
                            }
                        }
                    }
    
                }
            }
    

    CSS,只贴了浮标的样式,bar同理。

                .buoy {
                    width: 12px;
                    height: 12px;
                    margin-bottom: 5px;
                }
                .buoy-moving-step-1{
                    animation: buoy-moving-step-1 1s ease-out;
                    animation-fill-mode: forwards;
                }
                .buoy-moving-step-2{
                    animation: buoy-moving-step-2 1.5s ease-out;
                    animation-fill-mode: forwards;
                }
                .buoy-moving-step-3{
                    animation: buoy-moving-step-3 1.8s ease-out;
                    animation-fill-mode: forwards;
                }
        @keyframes buoy-moving-step-1 {
            0% {
                margin-left: 0;
            }
            100% {
                margin-left: 111px;
            }
        }
        @keyframes buoy-moving-step-2 {
            0% {
                margin-left: 0;
            }
            100% {
                margin-left: 222px;
            }
        }
        @keyframes buoy-moving-step-3 {
            0% {
                margin-left: 0;
            }
            100% {
                margin-left: 300px;
            }
        }
    

    2. transition ,transform, translate三者的用法

    从英文释义上来理解:
    transform:变换,参数可以是translate,scale,rotate等;
    translate:位移,是transform的一个属性;
    transition:过渡,是唯一有时间参数的!transform可以作为他的一个参数。
    例子:

    transition:transform 2s ease-in , border-radius 3s ease-out; //可同时设置多个属性的动画,用逗号隔开
    
    transform:translateX(50px);
    

    3. 动画性能对比 transition < transform ,position < translate,animation适合场景

    写法举例,我们实现一个动画,鼠标悬浮在元素上,元素的宽度变化。

    transition方式:

    <body>
        <div class="foo"></div>
    </body>
    <style>
        .foo {
            height: 100px;
            width: 100px;
            transition: height 1s linear;
        }
    
        .foo:hover {
            width: 200px;
        }
    </style>
    

    transform 方式:(也是要使用transition的)

    <body>
        <div class="foo"></div>
    </body>
    <style>
        .foo {
            height: 100px;
            width: 100px;
            transition: transform 1s linear;
        }
    
        .foo:hover {
            transform: scaleX(2);
        }
    </style>
    

    animation 方式:

    .block {
            animation: widen 2s ease;
            animation-fill-mode: forwards;
        }
    
        @keyframes widen {
            from {
                width: 100px;
            }
            to {
                width: 200px;
            }
        }
    

    铺垫知识

    • 浏览器渲染页面的任务由两个线程完成:主线程 和 排版线程
    • GPU:
      GPU上合成涂层可以在涉及大量像素的绘图和合成操作中实现比CPU还要好的效率,硬件专为这些类型的负载而设计。更详细的知识参考链接:https://www.smashingmagazine.com/2016/12/gpu-animation-doing-it-right/
    • 渲染过程:
      不同属性值引起的重新绘制有3种路径:
      1. layout->paint->composite
      2. paint->composite
      3. composite
        CSS的属性也就此分为3大类:布局类(layout),绘制类(paint),合成类(composite)
        composite 属性目前只有两个:transform和opacity

    transition:

    transition做动画时两个线程的工作情况是:对于浏览器来说,元素的高度一直在变化,因此这个动画的每一帧都需要主线程对元素进行布局,绘制成位图,将位图交由GPU线程,GPU将位图绘制到屏幕。两个线程来回切换工作,即使是移动十几个像素,主线程也需要对元素布局很多次,这部分的工作消耗相当大,相对较慢,这也是transition动画经常卡顿的原因。


    CSS_transition的性能探究.png

    transform:

    使用transform时浏览器的工作情况是:主线程对元素进行布局,绘制成位图,交由GPU线程,transform执行的整个过程都在GPU进程执行绘制,两个线程来回切换的情况不多,而且transform不会触发浏览器的重新排版,不会影响周围的布局,这也意味着这种情况的动画比transition流畅一些。

    CSS_transform的性能探究.png

    position VS translate

    当页面需要位移动画时,可能会用到这两种,position的原理和transition符合,会触发浏览器的重排,translate不会,所以最好选择transform的translate,rotate,scale等方法。

    animation

    transition是使一个或多个属性值产生过渡效果,animation则作用于元素本身,强调流程与控制,是关键帧动画的范畴。简单的效果可以用animation,复杂的或想要更自由地掌控应该选择animation。我认为animation会更占资源一些。

    硬件加速 will-change + translateZ(0)

    transform:translate3d(0,0,0);
    transform:translateZ(0);
    will-change:transform;
    

    参考:
    https://www.smashingmagazine.com/2016/12/gpu-animation-doing-it-right/
    https://juejin.im/entry/59dc9aedf265da43200232f9

    相关文章

      网友评论

          本文标题:css3动画transition transform性能对比及原

          本文链接:https://www.haomeiwen.com/subject/cktonhtx.html