CSS动画

801 阅读4分钟

动画的原理

定义

由许多静止的画面(帧),以一定的速度(如每秒30张)连续播放时肉眼会因为视觉残象产生错觉
而误以为是活动的画面

概念

帧:每一个静止的画面都叫做帧
播放速度:每秒24帧(动画,影视),每秒30帧(游戏)

举例:将div 从左向右移动

原理
每过一段时间(用setInterval可以做到),将div移动一小段距离,直到移动到目标地点

注意浏览器性能,绿色表示从新绘制(repaint)
css 渲染过程依次包含: 布局<绘制<合成;布局,绘制有可能被省略

setInterval 计时器

setInterval(() => {},1000)

var n = 1
setInterval(() => {console.log(n)
    n=n+1
    demo.style.left=n+'px'}
    ,1000) 
让一个div向左移动,demo的样式向左 n+px

var n = 1
var id = setInterval(()=>{ 
    if(n <=200){
        demo.style.left=n+'px'} 
        n = n + 1
    }else{
        clearInterval(id)}
    },1000/60)
setInterval不会停止,会一直运行下去,在开始时获取一个id,使用id暂停

transform:translateX(0 =>300px)
不要使用left做动画,因为left需要走全部渲染流程;使用transform(变形),只走合成流程
直接修改会被合成,需要加延迟

CSS 渲染

浏览器的渲染过程

根据HTML构建HTML树(DOM)
根据CSS构建CSS树 (CSSOM)
将两棵树合并成一颗渲染树(rendtree)
Layout布局(定位)(文档流,盒模型,计算大小和位置)
panint绘制(把边框颜色,文字颜色,阴影等画出来)
composiet合成(根据层叠关系展示画面)(把各层之间拍平,然后渲染到界面上)

三棵树的结构图

跟新样式

div.style.background="red"
div.style.display ="none" 
div.classList.add("red")          
div.remove()

三种渲染方式

JS/CSS > 样式 > 布局 > 绘制 > 合成
javascript > style > Layout > Paint > composite

第一种流程全走
div.remove()会触发当前消失,其它元素relayout
JS/CSS > 样式 > (布局) > 绘制 > 合成
javascript > style > (Layout) > Paint > composite

第二种跳过Layout
改变背景颜色,直接repaint+composite
JS/CSS > 样式 > (布局) > (绘制) > 合成
javascript > style > (Layout) > (Paint) > composite

第三种跳过Layout,paint
改变transform,只需要composite

点击查看:所有渲染流程

动画优化

js优化
使用requestAnimationFrame 代替 setTimeout 或 setInterval

css优化
使用will-change 或 translate

transform (变形)

4个常用功能

位移:translate
缩放:scale
旋转:rotate
倾斜:slcew

一般都配合transition过渡,inline元素不支持transform,需要变成block元素

常用代码

translateX(50px)    往右移动50px
translateZ          三维图的直上直下屏幕距离你的远近,二维图时没变化
perspective:1000px; 透视图的原点在1000px这,正中心1000px,三维图的属性
translate(50px 50px)往右,往下50px

translate,让绝对定位元素居中
left:50%;
top:50%;
transform:translate(-50%,-50%)

transition:all 1s;     1秒 的 动画 效果
transform:scale(1.5);  缩放1.5倍 ,一般不咋用,容易模糊
transform:rotate(45deg)旋转45°
transform:skewX(15deg) 向X的方向上倾斜15°

transition(过渡)

作用

添加中间帧,告诉开头,中间,结尾,怎么样

语法

transition:left 200ms linear 100ms
transition:属性名 时长 过渡方式 延迟

transition:left 200ms,top 400ms
可以用逗号分隔2个不同属性

transition:all 200ms
可以用all代替所有属性

过渡方式

linear       线性,匀速
ease         缓动
ease-in      先慢后快
ease-out     淡出
ease-in-out  淡入而且淡出
cubic-bezier
step-start
step-end
steps

完整代码

transition:all 2s linear 2s;动画效果2秒内触发,线性匀速,延迟2秒开始

属性过渡(不是所有属性都能过度)

background;                    可以过渡
opacity;                       可以过渡
display:none        => block   不能过渡
visibility:hidden   => visible 可以过渡

区别
display:none;      显示为无,不占位置
visibility:hidden; 将元素隐藏,但位置还在

过渡必须有起始,一般只有一次或二次动画;比如hover和非hover状态的过渡

animation 动画介绍

@keyframes 需要声明关键帧

语法

@keyframes slidein{
    from{
        transform: translateX(0%)
    }
    to{
        transform: translateX(100%)
    }
}

@keyframes identifier{
    0%{top: 0; left: 0;}
    30%{top: 50px;}
    68%,72%{left: 50px;}
    100%{top: 100px; left: 100%;}
}
使用forwards,让动画帧停在最后一帧

animation 缩写语法

animation:时长,过渡方式,延迟,次数,方向,填充模式,是否暂停,动画名

时长       1s或1000ms
过渡方式   跟transition 一样
次数       3或者2.4或者infinite(无限次数)
方向       reverse(反过来),alternate(交替的),alternate-reverse(先回来,在出去)
填充模式   none,forwards,both,backwards(开始把动画的第一帧复制到开始位置)
是否暂停   paused(暂停),running(恢复)

练习代码:

transform 会动的心脏

animatioin 跳动的心脏