css3动画transition transform性能对比及原理,用animation实现进度条动效

本文你将看到:

  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

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,033评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,725评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,473评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,846评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,848评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,691评论 1 282
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,053评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,700评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,856评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,676评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,787评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,430评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,034评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,990评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,218评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,174评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,526评论 2 343