CSS动画小知识

接着前文看《CSS权威指南》,本文整理一些CSS动画的知识点,同时给出一些例子。

预备知识

变形 Transform

在CSS动画中我们经常需要通过变形来达到一些奇妙的效果。使用 transform 首先要明确变形是基于笛卡尔坐标系,也就是通常所说的 x/y/z

  • transform 是基于物体自身的坐标系,百分比也是基于自身的大小
  • 移动和旋转的前后顺序很重要,因为物体旋转之后的坐标系也跟着旋转
  • 常用函数(live demo):
    • 平移函数:translateXtranslateYtranslateZtranslatetranslate3d
    • 缩放函数:scaleXscaleYscaleZscalescale3d( number, number, number )
    • 旋转函数:rotateXrotateYrotateZrotaterotate3d( number, number, number, angle)
    • 倾斜函数:skewXskewYskew
    • 视域:perspective( length )
  • 重要属性:transform-origintransform-stylebackface-visibility
See the Pen FlipCard on CodePen.

贝塞尔曲线

在过渡或者动画效果中,我们可能需要使用贝塞尔曲线 cubic-bezier 来控制动画的步调。我们可以在这里 设置不同的曲线并预览,或者在这里 查看一些常用的曲线

动画

属性

  • animation-name:指定动画的名称
  • animation-duration:定义动画的时长(ms | s)
  • animation-iteration-count:声明动画的迭代次数(number | infinite)
  • animation-direction:设置动画播放的方向(normal | reverse | alternate | alternate-reverse)
  • animation-delay:延迟播放动画
  • animation-timing-function:改变动画的内部时序
  • animation-play-state:设置动画的播放状态(running | paused)
  • animation-fill-mode:动画的填充模式,也就是动画结束之后的状态(normal | forwards | backwards | both),最终的显示效果与 animation-direction 属性有关
    live demo
JS动画事件
  • animationstart:动画开始
  • animationiteration:每次迭代开始
  • animationend:动画结束

动画延迟效果

给不同对象赋予一定的延迟时间,往往可以形成一些有趣的动画效果。这里我们要区分两种延迟:

  • 浏览器把动画附加到元素上之后等待多久开始第一次迭代:animation-delay: <time>
  • 每次迭代开始前需要等待:重复关键帧
    /*假设一个小球来回滚动,每次在两边时停留800ms再继续滚动,我们可以由以下动画控制*/
    .ball {
      width: 50px;
      height: 50px;
      border-radius: 50%;
      background-color: orange;
      animation: move 2000ms infinite alternate;/*alternate 设置来回滚动*/
    }
    @keyframes move {
      0%,
      40% {
        transform: translateX(0);/*重复关键帧模拟延迟,2000ms × .4 = 800ms*/
      }
      60%,
      100% {
        transform: translateX(250px);/*重复关键帧模拟延迟,2000ms × .4 = 800ms*/
      }
    }
    复制代码
    live demo

从中间帧开始执行动画

如果animation-delay的值为负,而且绝对值比animation-duration 小,那么动画将立即开始并且从中间的关键帧开始播放。例如,一个动画时长为 10s,延迟时间为 -4s,那么如果 animation-timing-functionlinear,则将从动画的 40% 开始播放

利用 box-shadow

利用 box-shadow 可以创建为单个元素创建多个 border。例如,我们可以利用这个属性为一个 loading 动画添加多个小的圆圈。

  • 语法:box-shadow: h-shadow v-shadow blur spread color inset;
  • 例子
// 我们通过变换box-shadow来交换正方形的位置
.spinner {
  position: absolute;
  /*border-radius: 50%; need width > 0 and height > 0*/
  width: 0;
  height: 0;
  box-shadow: 
    -30px -30px 0 40px #a593e0, 
    -30px 30px 0 40px #e0e3da,
    30px 30px 0 40px #fffff3, 
    30px -30px 0 40px #566270;
  animation: spin 3000ms infinite alternate;
}
复制代码

利用伪元素

我们注意到利用 box-shadow 属性,所有“子元素”是绑定在“父元素”上且同时变化的。如果我们不想引入多余的 DOM 元素,同时又想“子元素”不与“父元素”同时进行变换,我们可以采用::after::before来创建。

来看一些有趣的例子吧

利用上述知识写的一些简单的动画(点击查看源码)

动画性能

讲完了一些基础知识,让我们进一步聊聊动画渲染的性能。

浏览器底层原理

浏览器的工作原理,请看 How Browsers Work: Behind the scenes of modern web browsers,写的很详尽,值得一读。

浏览器处理的过程很简单:计算元素的样式(重新计算样式),生成每个元素的几何形状和位置(布局),绘制图层中的每个像素(初始化绘图并且进行绘图)并且将图层绘制到屏幕上(图层的合成)

浏览器内部

现代浏览器通常有两个主要的线程:① main thread;② compositor thread

  • 主线程的主要职责是(维持一个RenderLayers):
    • 运行脚本
    • 计算 HTML 元素的 CSS 属性
    • 页面布局
    • 把 DOM 元素绘制到一个或者多个位图上
    • 把合成的位图交给compositor thread
  • 合成线程的主要职责是(维持一个 GraphicsLayers):
    • 通过 GPU 把位图绘制到屏幕上
    • 请求主线程更新呈现在屏幕上或者即将呈现在屏幕上的位图
    • 当进行滚动操作时,弄清楚哪部分即将呈现在屏幕上
    • 当进行滚动的时候,移动相应部分的页面

合成线程会尽可能响应用户的鼠标键盘等消息事件。可能发生的情况是,当页面滚动需要更新视图时,合成线程以每帧(60fps)请求更新位图(刷新屏幕),但主线程上可能正进行复杂的脚本运算或者HTML元素绘制,导致合成线程无法及时拿到位图,这时合成线程会绘制空白。

GPU

GPU 能够很快地处理将位图绘制到屏幕上的操作,还能很快处理将同一位图通过变换再次绘制的操作,但是对于从内存中加载位图的处理比较慢。比较一个过渡效果使用 height 和 transform 的两个流程:

composited layer 创建的条件
  • 使用视频加速解码的 video 元素
  • flash、使用3D (WebGL) context 的 canvas 元素
  • CSS transform
  • CSS filter
  • CSS opacity

高性能的 CSS动画

减少消耗成本

为什么有些动画播放流畅,有些则显得很卡顿呢?从上面的知识中,我们或许会得到一些启发:现代浏览器在完成 position(位置), scale(比例缩放), rotation(旋转) 和 opacity(透明度)这四种属性的动画时,消耗成本较低。

如果我们使用 height 进行变换,浏览器可能在每帧需要请求主线程重新布局、绘制和更新位图,再将位图从 CPU 传给 GPU,这个过程可能导致卡顿,也就是我们丢失了某些关键帧。

但是使用 height 的性能就一定比 transform 的性能差?不一定,可能的情况是:① 绘制的位图很小;② height 更新不会影响其他元素的布局等情况;③ 元素是脱离正常流的;

我们在使用 width、display、font-size、box-shadow、color 等可能引起重排或者重绘的属性时,如果你不能清楚的知道自己在做什么,我们还是建议使用推荐的操作避免糟糕的情况出现。

JS动画和CSS动画的优缺点
  • 优点:JavaScript中的动画可以为你提供更多的控制,比如开始,暂停,回放,中断和取消等,还可以进行设计复杂的动画效果。缺点:主线程上可能进行复杂的运算,增大掉帧的风险(我们也可以放在 Web Worker 中进行)。
  • 优点:浏览器会对CSS动画进行优化,如果有需要,它会创建图层,并且可以在主进程之外完成一些操作。缺点就是CSS动画相对于Javascript动画而言,缺乏表现力,对动画的设计来说更加复杂。

参考博客及推荐阅读

转载于:https://juejin.im/post/5d2706aae51d4555fc1acd2b

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值