transition
- transition: property duration timing-function delay;
- transition-property: width; 规定应用过渡的CSS属性的名称
- transition-duration: 2s; 定义过渡效果花费的时间,默认为0
- transition-timing-function: linear; 规定过渡效果的时间曲线,默认是ease
- transition-delay: 2s; 规定过渡效果何时开始,默认为0
animation
需要运用@keyframes规则和animation属性
div{ |
属性名 | 作用 |
---|---|
animation-name | 规定 @keyframes 动画的名称 |
animation-duration | 规定动画完成一个周期所花费的秒或毫秒。默认是 0。 |
animation-timing-function | 规定动画的速度曲线。默认是ease。linear |
animation-delay | 规定动画何时开始。默认是 0。 |
animation-iteration-count | 规定动画被播放的次数。默认是 1。infinite |
animation-direction | 规定动画是否在下一周期逆向地播放。默认是normal。alternate轮流反向播放 |
animation-play-state | 规定动画是否正在运行或暂停。默认是running。paused |
animation-fill-mode | 规定对象动画时间之外的状态。forwards保持最后一个属性,backwards应用开始属性 |
transition和animation也可以结合,以编排不同段用不同的曲线。
@keyframes mykf { |
贝塞尔曲线
timing-function使用的是三次贝塞尔曲线。贝塞尔曲线是一种插值曲线,它描述了两个点之间的差值来形成连续的曲线形状的规则。 一个量从一个值变化到另一个值,插值可以让它平滑地过渡。k次贝塞尔插值算法需要k+1个控制点。一次贝塞尔插值就是线性插值,公式:
$$
B(t)=P_0+(P_1-P_0)t=(1-t)P_0+tP_1, t\in[0,1]
$$
二次贝塞尔插值有三个控制点,公式:
$$
B(t)=(1-t)^2P_0+2t(1-t)P_1+t^2P_2, t\in[0,1]
$$
三次贝塞尔插值是两次二次贝塞尔插值的结果,再做一次贝塞尔插值:
$$
B(t)=(1-t)^3P_0+3t(1-t)^2P_1+3t^2(t-1)P_2+t^3P_3, t\in[0,1]
$$
cubic-bezier是在animation和transition中生产速度曲线的函数,格式为cubic-bezier(<x1>, <y1>, <x2>, <y2>)
,用法如下:
transition: all 2s cubic-bezier(.17, .86, .73, .14); |
cubic-bezier 的取值范围:
- P0:默认值 (0, 0)
- P1:动态取值 (x1, y1)
- P2:动态取值 (x2, y2)
- P3:默认值 (1, 1)
常见的cubic-bezier值:
- ease:cubic-bezier(.25, .1, .25, .1)
- linear:cubic-bezier(0, 0, 1, 1)/cubic-bezier(1, 1, 0, 0)
- ease-in:cubic-bezier(.42, 0, 1, 1)
- ease-out:cubic-bezier(0, 0, .58, 1)
- ease-in-out:cubic-bezier(.42, 0, .58, 1)
transform
2D方法
translate(left, top),位移,根据给定的left和top位置参数元素从当前位置移动
rotate(Xdeg),旋转,元素顺时针(X为负则逆时针)旋转X角度
scale(x, y),缩放,元素的尺寸根据给定的宽度和高度增加或减少倍数,负值会使其左右翻转
skew(xdeg, ydeg),倾斜,元素根据给定的水平线和垂直线参数翻转给定的角度
matrix(a, b, c, d, e, f),将所有2D转换方法组合,参数为六个,对应的矩阵及其变换公式为
$$
\left[
\begin{matrix}
a & c & e\
b & d & f \
0 & 0 & 1
\end{matrix}
\right]
\times
\left[
\begin{matrix}
x\
y \
1
\end{matrix}\right]
\left[
\begin{matrix}
ax + cy + e\
bx + dy + f\
1
\end{matrix}
\right]
$$
结果第一行为水平坐标,第二行为垂直坐标位移:transform: matrix(1, 0, 0, 1, 100, 100); 向右移动100
缩放:transform: matrix(s, 0, 0, s, 0, 0); 放大s倍
旋转:transform: matrix(cosθ,sinθ,-sinθ,cosθ,0,0); 旋转θ°
拉伸:transform: matrix(1,tan(θy),tan(θx),1,0,0)
3D方法
- translateX(x)/translateY(y)/translateZ(z),元素在X/Y/Z方向上的位移
- rotateX(angle)/rotateY(angle)/rotateZ(angle),元素围绕X/Y/Z轴以给定的度数旋转
- scaleX(x)/scaleY(y)/scaleZ(z),元素在X/Y/Z方向上的缩放
- scale3d(x, y, z),元素的缩放
- perspective: num,设置元素被查看时元素距视图的距离,以像素为单位
- perspective-origin: x-axis y-axis,定义元素所基于的X轴与Y轴,改变3D元素的底部位置
requestAnimationFragment
特点
- 浏览器会确保fn的执行在浏览器一帧的开头
- 浏览器会自动调节帧率,间接调节了fn的执行频率
不支持raf的浏览器中通常使用setTimeout(fn, 16.7)来实现(16.7ms为每秒60帧的一帧间隔时间)
每一帧执行的过程:JavaScript->Style->Layout->Paint->Composite
JavaScript的执行是在一帧的开头,若浏览器要更新屏幕但当前帧还未完成,那么当前帧就会被丢弃,延迟到下一次更新,即丢帧。尽可能缩短JavaScript执行时间至10ms以内
当有一个大任务的时候,可以分散到每一帧中去执行,比如绘制100个小球,可以每一帧绘制一个,而不是一帧绘制100个
使用requestAnimationFragment注意:
- 纯计算型、不涉及DOM访问的任务,可以放进Web Workers中
- 可以使用CSS实现的动画不要用JavaScript实现
- 对于用户事件的响应,逻辑尽量简单,复杂的逻辑可以延迟处理或分块处理
Style & Layout
使用JavaScript通常的最佳时间是先读取后设置。比如先读取offsetTop再设置top这样不会触发reflow
设置动画时,尽量避免直接改变元素的layout,比如使用transform
Paint
可以将DOM提升到新的composite layer,避免对整个层重新绘制,比如will-change: top;或是使用transform和opacity,这两个被视为合成器属性,在默认情况下会生成新的paint layer
Composite
在Paint阶段可能会发生在多个layer上,最后浏览器通过合并多个layer,根据他们的顺序来正确显示在屏幕上
composite layer提升条件如:
- 3D相关的CSS样式
- will-change设置为opacity、transform、top、left、bottom、left
- fixed(低DPI上不会提升)
- Hardware-accelerated video element
- Hardware-accelerated 2D canvas
- 3D WebGL
- Overlay(比如A覆盖在B上,而B是提升的composite layer,则A也会被提升到新的layer)
composite layer直接在GPU上完成,渲染速度非常快,但会消耗额外的内存
z-index、absolute等会生成paint layer,每个DOM node都会有对应的layout对象,如果layout对象在同一个坐标系空间,就会在同一个paint layer上。默认情况下,paint layer共享同一个composite layer。
参考文章