怕标题起的有点大,下述技巧如果你已经掌握了看看就好,欢迎斧正,本文希望通过介绍一些 CSS 不太常用的技巧,辅以一些实践,让读者可以更加深入的理解掌握 CSS 动画。

废话少说,直接进入正题,本文提到的动画不加特殊说明,皆指 CSS 动画。

正负旋转相消

嗯。名字起的很奇怪,好像数学概念一样。

(写完文章才发现这里应该叫正反旋转相消,图都截完了,大家心里清楚就好)

在动画中,旋转是非常常用的属性,

{
transform: rotate(90deg);
}

那旋转有一些什么高级点的技巧呢?当然是可以改变 transfrom-origin ,改变旋转中心点啦。

开个玩笑,改变旋转中心点这个估计大家都知道了,这里要介绍的技巧是利用父级元素正反两个方向的旋转,来制作一些酷炫的 3d 效果。

首先假设一下场景,我们有这样的一层 HTML 结构:

<div class="reverseRotate">
<div class="rotate">
<div class="content">正负旋转相消3D动画</div>
</div>
</div>

样式如下:

.content 内是我们的主要内容,好了,现在想象一下,如果祖先元素 .rotate 进行正向 linear 360° 旋转,父级元素 .reverseRotate 进行反向 linear 360° 旋转,效果回是啥样?

CSS 代码如下:

.rotate {
animation: rotate 5s linear infinite;
} .reverseRotate {
animation: reverseRotate 5s linear infinite;
} @keyframes rotate {
100% {
transform: rotate(360deg);
}
} @keyframes reverseRotate {
100% {
transform: rotate(-360deg);
}
}

神奇!因为一正一反的旋转,且缓动函数一样,所以整个 content 看上去依然是静止的!注意,这里整个 content 静止的非常重要。

有读者看到这里就要骂街了,作者你个智障,静止了不就没动画了吗?哪来的动画技巧?

别急!虽然看上去是静止的,但是其实祖先两个元素都是在旋转的!这会看上去风平浪静的效果底下其实是暗流涌动。用开发者工具选取最外层祖先元素是这样的:

既然如此,我们继续思考,如果我在其中旋转的一个祖先元素上,添加一些别的动画会是什么效果?想想就很刺激啊。

为了和文案里面的 3D 动画扯上关系,我们先给这几个元素添加 3D 转换:

div {
transform-style: preserve-3d;
perspective: 500px;
}

接着,尝试修改上面的旋转动画,在内层旋转上额外添加一个 rotateX:

@keyframes rotate {
0% {
transform: rotateX(0deg) rotateZ(0deg);
}
50% {
transform: rotateX(40deg) rotateZ(180deg);
}
100% {
transform: rotateX(0deg) rotateZ(360deg);
}
}

效果如下:

Wow,这里需要好好理解一下。由于内容 content 层是静止的但其实外层两个图层都在旋转,通过设置额外的 rotateX(40deg) ,相当于叠加多了一个动画,由于正反旋转抵消了,所有整个动画只能看到旋转的 rotateX(40deg) 这个动画,产生了上述的效果。

CodePen Demo -- Css正负旋转相消动画

动画相同,缓动不同

好的,继续下一个小技巧。

有的时候我们页面存在一些具有相同动画的元素,为了让动画不那么死板,我们可以给相同的动画,赋予不同的缓动函数,来达到动画效果。

假设我们有如下的结构:

<div class="container">
<div class="ball ball1"></div>
<div class="ball ball2"></div>
<div class="ball ball3"></div>
</div>

样式如下:

我们给它们相同的动画,但是赋予不一样的缓动函数(animation-timing-function),就像这样:

.ball1 {
animation: move 1s ease-in infinite alternate;
} .ball2 {
animation: move 1s linear infinite alternate;
} .ball3 {
animation: move 1s ease-out infinite alternate;
} @keyframes move {
100% {
transform: translateY(5vw);
}
}

这样,一个简单的 loading 效果就制作好了。(当然这个技巧比较简单,学会合理运用是关键)

CodePen Demo -- 动画相同,缓动不同

奇妙的缓动

缓动函数 timing-function 在动画中占据了非常重要的地位。

当你不想使用 CSS 默认提供的 linearease-inease-out 之类缓动函数的,可以自定义 cubic-bezier(1, 1, 0, 0),这里有个非常好用的工具推荐,下面这个网站,可以方便的调出你需要的缓动函数并且拿到对应的 cubic-bezier 。

cubic-bezier.com

过渡取消

我们在制作页面的时候,为了让页面更加有交互感,会给按钮,阴影,颜色等样式添加过渡效果,配合 hover 一起使用。

这个是常规思维,如果我们的元素一开始是没有过渡效果,只有 hover 上去才给它添加一个过渡,又或者一开始元素是有过渡效果的,当我们 hover 上去时,取消它的过渡,会碰撞出什么样的火花呢?

使用这个技巧(也许算不上技巧,纯粹好玩),我们可以制作出一些有趣的效果,例如下面这个感觉是利用就 JS 才完成的动画,其实是纯 CSS 动画:

其实就小圆圈是元素默认是带有 transition 的,只有在 hover 上去的时候,取消它的过渡,简单的过程:

  1. 由于一开始它的颜色的透明的,而 hover 的时候会赋予它颜色值,但是由于 hover 时过渡被取消了,所有它会直接显示。

  2. hover 离开的时候,它的原本的过渡又回来了,这个时候它会从有颜色到透明值缓慢渐变消失。

可以戳这里感受一下:

CodePen Demo -- Cancle transition

动画层级的控制,保持动画层级在最上方

这个问题可能有一点难理解。需要了解 CSS 动画渲染优化的相关知识。

先说结论,动画层级的控制的意思是尽量让需要进行 CSS 动画的元素的 z-index 保持在页面最上方,避免浏览器创建不必要的图形层(GraphicsLayer),能够很好的提升渲染性能。

OK,再一次提到了图形层(GraphicsLayer),这是一个浏览器渲染原理相关的知识(WebKit/blink内核下)。

简单来说,浏览器为了提升动画的性能,为了在动画的每一帧的过程中不必每次都重新绘制整个页面。在特定方式下可以触发生成一个合成层,合成层拥有单独的 GraphicsLayer。

需要进行动画的元素包含在这个合成层之下,这样动画的每一帧只需要去重新绘制这个 Graphics Layer 即可,从而达到提升动画性能的目的。

那么一个元素什么时候会触发创建一个 Graphics Layer 层?从目前来说,满足以下任意情况便会创建层:

  • 硬件加速的 iframe 元素(比如 iframe 嵌入的页面中有合成层)
  • 硬件加速的插件,比如 flash 等等
  • 使用加速视频解码的 元素
  • 3D 或者 硬件加速的 2D Canvas 元素
  • 3D 或透视变换(perspective、transform) 的 CSS 属性
  • 对自己的 opacity 做 CSS 动画或使用一个动画变换的元素
  • 拥有加速 CSS 过滤器的元素
  • 元素有一个包含复合层的后代节点(换句话说,就是一个元素拥有一个子元素,该子元素在自己的层里)
  • 元素有一个 z-index 较低且包含一个复合层的兄弟元素

本题中说到的动画层级的控制,原因就在于上面生成层的最后一条:

元素有一个 z-index 较低且包含一个复合层的兄弟元素。

这里是存在坑的地方,首先我们要明确两点:

  1. 我们希望我们的动画得到 GPU 硬件加速,所以我们会利用类似 transform: translate3d() 这样的方式生成一个 Graphics Layer 层。
  2. Graphics Layer 虽好,但不是越多越好,每一帧的渲染内核都会去遍历计算当前所有的 Graphics Layer ,并计算他们下一帧的重绘区域,所以过量的 Graphics Layer 计算也会给渲染造成性能影响。

记住这两点之后,回到上面我们说的坑。

假设我们有一个轮播图,有一个 ul 列表,结构如下:

<div class="container">
<div class="swiper">轮播图</div>
<ul class="list">
<li>列表li</li>
<li>列表li</li>
<li>列表li</li>
<li>列表li</li>
</ul>
</div>

假设给他们定义如下 CSS:

.swiper {
position: static;
animation: 10s move infinite;
} .list {
position: relative;
} @keyframes move {
100% {
transform: translate3d(10px, 0, 0);
}
}

由于给 .swiper 添加了 translate3d(10px, 0, 0) 动画,所以它会生成一个 Graphics Layer,如下图所示,用开发者工具可以打开层的展示,图形外的黄色边框即代表生成了一个独立的复合层,拥有独立的 Graphics Layer 。

但是!在上面的图中,我们并没有给下面的 list 也添加任何能触发生成 Graphics Layer 的属性,但是它也同样也有黄色的边框,生成了一个独立的复合层。

原因在于上面那条元素有一个 z-index 较低且包含一个复合层的兄弟元素。我们并不希望 list 元素也生成 Graphics Layer ,但是由于 CSS 层级定义原因,下面的 list 的层级高于上面的 swiper,所以它被动的也生成了一个 Graphics Layer 。

使用 Chrome,我们也可以观察到这种层级关系,可以看到 .list 的层级高于 .swiper

所以,下面我们修改一下 CSS ,改成:

.swiper {
position: relative;
z-index: 100;
} .list {
position: relative;
}

这里,我们明确使得 .swiper 的层级高于 .list ,再打开开发者工具观察一下:

可以看到,这一次,.list 元素已经没有了黄色外边框,说明此时没有生成 Graphics Layer 。再看看层级图:

此时,层级关系才是我们希望看到的,.list 元素没有触发生成 Graphics Layer 。而我们希望需要硬件加速的 .swiper 保持在最上方,每次动画过程中只会独立重绘这部分的区域。

总结

这个坑最早见于张云龙发布的这篇文章CSS3硬件加速也有坑,这里还要总结补充的是:

  • GPU 硬件加速也会有坑,当我们希望使用利用类似 transform: translate3d() 这样的方式开启 GPU 硬件加速,一定要注意元素层级的关系,尽量保持让需要进行 CSS 动画的元素的 z-index 保持在页面最上方。

  • Graphics Layer 不是越多越好,每一帧的渲染内核都会去遍历计算当前所有的 Graphics Layer ,并计算他们下一帧的重绘区域,所以过量的 Graphics Layer 计算也会给渲染造成性能影响。

  • 可以使用 Chrome ,用上面介绍的两个工具对自己的页面生成的 Graphics Layer 和元素层级进行观察然后进行相应修改。

  • 上面观察页面层级的 chrome 工具非常吃内存?好像还是一个处于实验室的功能,分析稍微大一点的页面容易直接卡死,所以要多学会使用第一种观察黄色边框的方式查看页面生成的 Graphics Layer 这种方式。

数字动画

很多技巧单独拿出来可能都显得比较单薄,我觉得最重要的是平时多积累,学会融会贯通,在实际项目中灵活组合运用,最近项目需要一个比较富有科技感的数字计数器,展示在线人数的不断增加。因为是内部需求,没有设计稿,靠前端自由发挥。

运用了上面提到的一些小技巧,参考了一些 CodePen 上的效果,整了个下述的 3D 数字计数效果,纯 CSS 实现,效果图如下:

CodePen Demo -- 3d Number Count

这个例子主要是想告诉大家,很多小的细节小的技巧合在一起,是可以作出非常酷炫的动画的。

最后

还有一些技巧,感觉本文的信息量已经够大了,所以可能会出个下篇。

系列 CSS 文章汇总在我的 Github ,持续更新,欢迎点个 star 订阅收藏。

好了,本文到此结束,希望对你有帮助 :)

如果还有什么疑问或者建议,可以多多交流,原创文章,文笔有限,才疏学浅,文中若有不正之处,万望告知。

你所不知道的 CSS 动画技巧与细节的更多相关文章

  1. 你所不知道的 CSS 滤镜技巧与细节

    承接上一篇你所不知道的 CSS 动画技巧与细节,本文主要介绍 CSS 滤镜的不常用用法,希望能给读者带来一些干货! OK,下面直接进入正文.本文所描述的滤镜,指的是 CSS3 出来后的滤镜,不是 IE ...

  2. 你所不知道的 CSS 阴影技巧与细节

    关于 CSS 阴影,之前已经有写过一篇,box-shadow 与 filter:drop-shadow 详解及奇技淫巧,介绍了一些关于 box-shadow 的用法. 最近一个新的项目,CSS-Ins ...

  3. 你所不知道的 CSS 阴影技巧与细节 滚动视差?CSS 不在话下 神奇的选择器 :focus-within 当角色转换为面试官之后 NPOI 教程 - 3.2 打印相关设置 前端XSS相关整理 委托入门案例

    你所不知道的 CSS 阴影技巧与细节   关于 CSS 阴影,之前已经有写过一篇,box-shadow 与 filter:drop-shadow 详解及奇技淫巧,介绍了一些关于 box-shadow  ...

  4. 你所不知道的 CSS 负值技巧与细节

    写本文的起因是,一天在群里有同学说误打误撞下,使用负的 outline-offset 实现了加号.嗯?好奇的我马上也动手尝试了下,到底是如何使用负的 outline-offset 实现加号呢? 使用负 ...

  5. 【CSS】346- 你所不知道的 CSS 阴影技巧与细节

    偷懒了1个多礼拜,在工作饱和的情况下,怎么坚持学习?今天的分享来自@Coco国服第一切图仔,我们聊聊CSS属性box-shadow- 关于 CSS 阴影,之前已经有写过一篇,box-shadow 与 ...

  6. 你可能不知道的Animation动画技巧与细节

    引言 在web应用中,前端同学在实现动画效果时往往常用的几种方案: css3 transition / animation - 实现过渡动画 setInterval / setTimeout - 通过 ...

  7. 你所不知道的CSS

    1.用FONT-SIZE:0来清除间距 inline-block的元素之间会受空白区域的影响,也就是元素之间差不多会有一个字符的间隙.如果在同一行内有4个25%相同宽度的元素,会导致最后一个元素掉下来 ...

  8. 你所不知道的Spring的@Autowired实现细节

    前言 相信很多Java开发都遇到过一个面试题:Resource和Autowired的区别是什么?这个问题的答案相信基本都清楚,但是这两者在Spring中是如何实现的呢?这就要分析Spring源码才能知 ...

  9. Android Context完全解析,你所不知道的Context的各种细节

    Context相信所有的Android开发人员基本上每天都在接触,因为它太常见了.但是这并不代表Context没有什么东西好讲的,实际上Context有太多小的细节并不被大家所关注,那么今天我们就来学 ...

随机推荐

  1. java封装性、继承性及关键字

    方法的参数传递(重点.难点)1.形参:方法声明时,方法小括号内的参数   实参:调用方法时,实际传入的参数的值 2.规则:java中的参数传递机制:值传递机制 1)形参是基本数据类型的:将实参的值传递 ...

  2. log4j(一)——为什么要用log4j?

    一:试验环境 OS:win7 JDK:jdk7 Log4j:1.2.17(好尴尬,原本是想试验下log4j2的,结果阴差阳错用了这个版本,不过幸好,试验也不白试验,试验的作用是一样的) 二:先看两个简 ...

  3. JVM GC(整理)

    1 GC类型 1 )YGC  一般情况下,当新对象生成,并且在Eden申请空间失败时,就好触发YGC ,堆Eden区域进行GC,清除非存活对象,并且把尚且存活的对象移动到Survivor区.然后整理S ...

  4. Java 三目运算符表达式的一些问题

    最近在处理一个需求,需求描述如下:对数据库中查询出来的数据的某一个字段做一个简单处理.处理方式是:如果该字段的值(取值范围0~4,有可能为null)等于0,那么默认处理成1. 测试代码如下: publ ...

  5. RabbitMQ入门-初识RabbitMQ

    初识RabbitMQ 要说RabbitMQ,我们不得不先说下AMQP.AMQP,即Advanced Message Queuing Protocol,高级消息队列协议,是应用层协议的一个开放标准,为面 ...

  6. Ubuntu系统的安装Sublime3

    1.添加Sublime-text-3软件包的软件源 sudo add-apt-repository ppa:webupd8team/sublime-text-3     2.使用以下命令更新系统软件源 ...

  7. 创建Git版本库

    什么是版本库呢?版本库又名仓库,英文名repository,你可以简单理解成一个目录,这个目录里面的所有文件都可以被Git管理起来,每个文件的修改.删除,Git都能跟踪,以便任何时刻都可以追踪历史,或 ...

  8. 用 Node.js 把玩一番 Alfred Workflow

    插件地址(集成Github.掘金.知乎.淘宝等搜索) 作为 Mac 上常年位居神器榜第一位的软件来说,Alfred 给我们带来的便利是不言而喻的,其中 workflow(工作流) 功不可没,在它上面可 ...

  9. jQuery相关知识总结一

    1day-jquery 1. 1 jQuery 1概念 * JavaScript(ECMA/DOM/BOM)在实际开发中,使用比较麻烦,有浏览器兼容问题. * JavaScript类库(JS库) 的目 ...

  10. ios-->制作ipa文件

    用证书进行真机调试并生成二级制文件,通常位于:/Users/.../Library/Developer/Xcode/DerivedData/XXXXXDemo-gmtamkryoesxilartayu ...