CSS动画

Get Started

• 动画的原理
• 浏览器渲染原理
• CSS动画优化
• transform全解
• transition过渡

动画

• 定义
有许多静止的画面(帧)
以一定的速度(如每秒30张)连续播放时
肉眼因视觉残像产生错觉而误以为是活动的画面
• 概念
帧:每个静止的画面都叫做帧
播放速度:每秒24帧(影视)或者每秒30帧(游戏)

一个最简单的例子
• 将一个div从左往右移动
• 原理
每过一段时间(用setInerval做到)
将div移动一小段距离
知道移动到目标地点
• 注意性能
绿色表示重新绘制(repaint)
CSS渲染过程一次包含布局,绘制,合成
其中布局和绘制有可能被省略

var n = 1

var id setInterval(() => {
  if (n <= 200) {
    demo.style.left = n + 'px'
    n = n + 1
  } else {
    clearInterval(id)
  }
}, 1000 / 60)

前端高手不用left做动画
• 用transform(变形)
• 原理
transform: translateX(0=>200px)
直接修改会被合成,需要等一会修改
transition过度属性可以自动脑部中间帧
transform只在页面刷新,动作开始动作结束时渲染。因此性能更高。
• 注意性能
并没有repaint(重新绘制)
比left性能好

#demo {
  width: 100px;
  height: 100px;
  border: 1px solid red;
  position: relative;
  left: 0;
}
#demo.end {
  transform: translateX(200px);
}
JS
steTimeout(()=>{
  demo.classList.add('end')
},3000)

浏览器渲染原理

参考文章
• Google团队写的文章
渲染树构建,布局及绘制
渲染性能
使用transform来实现动画
• 查看CSS个属性触发什么
CSSTriggers.com

浏览器渲染过程

• 步骤
根据HTML构建HTML树(DOM)
根据CSS构成CSS树(CSSDOM)
将两棵树合并成一颗渲染树(render tree)
Layout布局(文档流,盒模型,计算大小和位置)
paint绘制(把边框颜色、文字眼色、阴影等画出来)
compose合成(根据层叠关系展示画面)

如何更新样式

• 一般我们用js来更新样式
比如 div.style.background = 'red'
比如 div.style.display = 'none'
比如 div.classList.add('red')加样式不如加类
比如 div.remove()直接删掉节点
• 这些方法有什么不同

有三种不同的渲染方式
  1. JS/CSS>样式>布局>绘制>合成
    更新方式:全走
    div.remove()会触发当前消失,其他元素relayout
  2. JS/CSS>样式>布局>绘制>合成
    更新方式:跳过layout
    改变背景颜色,直接repaint+composite
  3. JS/CSS>样式>合成
    更新方式:跳过layout和paint
    改变transform,只需要composite
    注意必须全屏查看效果,在iframe里看有问题

到底哪个样式,怎么样更新样式:https://csstriggers.com/

CSS动画优化

答案都在Google写的文章里
• JS优化
使用requestAnimationFrame代替setTimeout或setInterval
• CSS优化
使用will-change或translate

transform全解

https://developer.mozilla.org/zh-CN/docs/Web/CSS/transform
• 四个常用功能
位移 translate
缩放 scale
旋转 rotate
倾斜 skew
• 经验
一般都需要配合transition过度
inline元素不支持transform,需要先变成block

translate

• 常用写法
translateX(<length-perventage>)
translateY(<length-perventage>)
translate(<length-perventage>,<length-perventage>?)
translateZ(<length>)且父容器perventage
Translat3d(x,y,x)
• Note
perspective: 1000px;
视图的原点在中心,范围是1000px

left: 50%;
top: 50%;
transform: translate(-50%, -50%);

定位元素居中,完美
transform: scaleX(1.5);变高变瘦
• border的宽度也会跟着变化
• 经验
要学会看懂MDN的语法示例
Translate(-50%,-50%)可做绝对定位元素的居中

scale

• 常用写法
scaleX(<number>)
scaleY(<number>)
scale(<number>,<number>)
• 经验
使用较少,因为会出现模糊

rotate
• 常用写法
rotate([<angle>|<angle>])
rotateZ([<angle>|<angle>])
rotateX([<angle>|<angle>])
rotateY([<angle>|<angle>])
rotate3d
• 经验
一般用于360°旋转制作loading
用到是再搜索rotate MDN看文档

skew

• 常用写法
skewX([<angle>|<zero>])
skewY([<angle>|<zero>])
skew([<angle>|<zero>],[<angle>|<zero>])
• 经验
使用较少,用到再搜文档

transform多重效果

• 组合使用
transform: scale(0.5) translate(-100%,-100%)
transform: none;取消所有

transition过渡

• 作用:补充中间帧
• 语法
transition:属性名 市场过渡方式 延迟
transition:left 200ms liner
可以用逗号分隔两个不同属性
transition: left 200,top 200ms
可以用all代表所有属性
transition:all 200ms
过渡方式有:liner|ease|ease-in|ease-out|ease-in-out|cubic-bezier|step-start|step_end|steps
https://developer.mozilla.org/zh-CN/docs/Web/CSS/timing-function

• 注意:并不是所有属性都可以过渡
display:none=>block没法过度
一般改成visibility:hidden=>visible(过渡到看不见,位置还占着。)
background眼色可以过渡(因为颜色是个数值)
opacity透明度可以过渡,过渡到0的时候只是看不见,位置还占着。(需要demo,remove()把这个扔掉才会没有)

过渡必须要有起始

一般只有一次动画,或者两次。比如hover和非hover状态的过渡

如果还有中间点?

两种办法
• 使用两次transform
.a === transform ===> .b
.b === transform ===> .c
如何知道了中间点呢
用setTimeout或者监听transitionend事件
http://js.jirengu.com/buwah/1/edit?html,css,js,output
• 使用animetion
声明关键帧
添加动画
让动画停在最后一帧:加个forwards
http://js.jirengu.com/peran/1/edit?html,css,output

keyframes语法
from to和百分数

@keframs slidein{
        from{
                transform(0%);
        }
        to{
                transform(100%);
        }
}
@keframs slidein{
        0% { top: 0;left: 1; }
        30% { top: 50px; }
        68%, 72% { left: 50px; }
        100% { top: 100px; left: 100%; }
}

• animation缩写语法
animation:时长|过渡方式|延迟|次数|方向|填充模式|是否暂停|动画名;
时长:1s或者1000ms
过渡方式:跟transition取值一样,如linear
次数:3或者2.4或者infinite
方向:reverse|laternate(常用)|alternate_reverse
填充模式: none|forwards|backwards|both
是否暂停: paused|tunning
以上所有属性都有对应的单独属性

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

推荐阅读更多精彩内容