阅读更多

0顶
0踩

移动开发

转载新闻 你所不知道的 CSS 动画技巧与细节

2017-09-19 14:00 by 副主编 jihong10102006 评论(0) 有14853人浏览
css
怕标题起的有点大,下述技巧如果你已经掌握了看看就好,欢迎斧正,本文希望通过介绍一些 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° 旋转,效果回是啥样?
.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 默认提供的 linear、ease-in、ease-out 之类缓动函数的,可以自定义 cubic-bezier(1, 1, 0, 0),这里有个非常好用的工具推荐,下面这个网站,可以方便的调出你需要的缓动函数并且拿到对应的 cubic-bezier 。

cubic-bezier.com

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

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

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

其实就小圆圈是元素默认是带有 transition 的,只有在 hover 上去的时候,取消它的过渡,简单的过程:
  • 由于一开始它的颜色的透明的,而 hover 的时候会赋予它颜色值,但是由于 hover 时过渡被取消了,所有它会直接显示。
  • 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 较低且包含一个复合层的兄弟元素。

这里是存在坑的地方,首先我们要明确两点:
  • 我们希望我们的动画得到 GPU 硬件加速,所以我们会利用类似 transform: translate3d() 这样的方式生成一个 Graphics Layer 层。
  • 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
  • 大小: 47.1 KB
  • 大小: 16.3 KB
  • 大小: 5.4 KB
  • 大小: 41.1 KB
  • 大小: 981.2 KB
  • 大小: 621.2 KB
  • 大小: 600 Bytes
  • 大小: 116 KB
  • 大小: 1.5 MB
  • 大小: 69.7 KB
  • 大小: 76.2 KB
  • 大小: 36.5 KB
  • 大小: 14 KB
  • 大小: 32.5 KB
  • 大小: 1.7 MB
来自: github
0
0
评论 共 0 条 请登录后发表评论

发表评论

您还没有登录,请您登录后再发表评论

相关推荐

  • 浅析可复用性,可维护性的相关概念

    简单的介绍了一下软件构造中两个比较重要的外部属性:可维护性和可复用性,他们的一些概念。

  • 可维护性、可复用性

    可维护性、可复用性可复用性介绍传统的复用可维护性低的原因可维护性提高的方法设计目标 可复用性介绍 可复用性(Reuseability)复用又叫重用,是重复使用的意思。一般软件的复用率并不高,尤其在国内。复用的好处可以得到 较高的生产效率以及随之而来的成本降低、较高的软件质量(错误可以更快的被纠正)以及 恰当的使用复用可以改善系统的可维护性。 传统的复用 1.代码的复制粘贴 2.使用已有的成熟算法 3.使用已有的数据结构 可维护性低的原因 1.过于僵硬:很难在一个软件系统里加入新的功能 2.过于脆弱:对一个地

  • 可维护性测试指南

    维护的主要定义是保持或维持特定状态的过程。软件的可维护性由开发人员负责,他们定期修改软件以满足不断变化的客户需求并解决客户提出的问题。软件维护需要增强软件的功能,以包含客户需要的新功能,修改代码以避免将来出现问题,修复代码中的缺陷或错误,并确保不存在安全漏洞。此外,软件维护通常包括发布更新,以提高适应性和有效性,并替换不受欢迎的功能。软件维护在很大程度上受到软件和代码质量的影响。质量较低的软件需要更多的维护。对于低质量软件,增加新需求或扩展现有代码的工作量和成本要高得多。

  • 可维护性?

    可维护性? 软件工程追求的目标之一就是可维护性,可维护性主要表现在3个方面:可理解性、可测试性和可修改性。面向对象的主要好处就是显著的改善了软件的可维护性。 posted on 2011-04-18 13:20 yeah 阅读(...) 评论(...) 编辑 收藏 ...

  • 可维护性的指标

    5.1 Metrics and Construction Principles for Maintainability 可维护性的度量与构造原则 1. 可维护性的指标 软件维护的类型:纠错性维护(25%)、适应性维护(21%)、完善性维护(50%)、预防性维护(4%) 可维护性(Maintainability)、可扩展性(Extensibility)、灵活性(Flexibility)、可适应性(Adaptability)、可管理性(Manageability)、支持性(Supportabil...

  • 软件架构的可维护性原则

    作者:禅与计算机程序设计艺术 《软件架构的可维护性原则》 引言 1.1. 背景介绍 随着信息技术的飞速发展,软件架构在软件开发中的重要性日益凸显。在软件架构设计过程中,可维护性是一个不容忽视的问题。可维护性是指软件系统在

  • 可维护性原则

    好的软件总是需要可维护性,那么这究竟需要遵循哪些原则呢? 众所周知,一个好的软件需要有好的可维护性。但是我们构造的软件系统往往有 着许多问题,导致一个软件的可维护性较低的原因有四个: 1.过于僵硬(Rigidity):很难在系统中加入新功能。因为会波及其它模块,最后会变成跨越几个模块的大改动。 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2.过于脆弱(Fragility):与过于僵硬同时存在。对一个地方的修改,往往导致看上去没有什么关系...

  • 软件可维护性综述

    软件可维护性综述 1. 软件维护的目标,任务,分类与特点 软件维护的目标: 通过必要的维护工作使得系统持久的满足用户的需要。 各类维护活动的根本目的是:延长软件生存期 软件维护的分类: 1 )改正性维护;2 )适应性维护; 3 )完善性维护;4 )预防性维护。 改正性维护:是改正在系统开发阶段已发生而系统测试阶段尚未发现的错误。 任务:为了识别和纠正软件错误、改正软件性能上的缺陷、排除实施中的误...

  • 什么是“可维护性”?

    从InfoQ上面看到的一个讨论,国外的牛人在抱怨NHibernate 2.1的“可维护性”太差,改个东西要牵动全身。接着有人回应,说NHibernate 2.1其实很好维护。争论到最后,就变成了对“可维护性”的定义了,毕竟大家各执一词,可能只是因为标准不同。 原文的链接:[url]http://www.infoq.com/cn/news/2009/08/what-is-maintainabl...

  • 【软件质量】软件可维护性

    本文介绍软件的可维护性

  • 如何编写复用性、可读性和可维护性的代码

    - 平时我们在写HTML、CSS时会为类的命名耗费脑汁,本文总结了一下平时编码的心得CSS结构化组织思想 目的是讲用户界面划分为独立的块,即使使用复杂的UI,这也使界面开发变得简单快捷,并且允许重复使用现有的代码,而无需复制和粘贴。 CSS(块+元素+修饰符) 块所谓的“块”其实就是该DOM元素共有的最基本的特性,在其命名上我们可以采取按照其目的来取名(btn或者search-f

  • 代码质量之可维护性

      我的心态变化 第一次接触编程,学习C语言,交换两个数的值:  c = a  a = b  b = c  后来我我从师兄那学到了下面这段代码,觉得写的比我之前的更漂亮: a = a + b  b = a - b  a = a - b  最后参加工作了,看到很多别人的代码,最后又觉得最漂亮的代码是这样的:  c = a  a = b  b = c  请问大家,为什么我的...

  • 可靠性 可用性 可维护性

    平均无故障时间 MTTF 可靠性 = MTTF/(1+MTTF) 无失效运作的概率 平均失效间隔时间 MTBF 可用性 = MTBF/(1+MTBF) 正确运作的概率 平均修复时间 MTTR 可维护性 = 1/(1+MTTR) 完成维护的概率

  • 保持应用系统可维护性的八个实际措施

    应用系统的可维护性主要表现在三点: 1. 可理解性: 是否很容易地理解软件的行为, 理解系统的功能是如何实现的; 2. 可识别性: 当出现错误时, 是否很容易地定位到错误的源头; 3. 可变化性: 当修复问题或扩展新功能时, 所做的修改和影响是否局限在更小的范围内。 每一个软件...

  • 非功能测试第一篇------可靠性、可移植性、 易用性 (了解即可)

    可靠性 什么时候需要关注可靠性? 涉及人身安全财产安全的时候 医疗 金融 客户的信息 ,资源等 关注点 ? ...

  • 提高程序的可读性以及可维护性

    对于简单的一个for循环,如: for(int i =1; i { //proceeding } 从语法上来讲,上述语句完全没有问题。但是可读性及可扩展性差,为什么呢? 因为使用了100这个具体的值作为循环上届,其意义不明确,i与100比较究竟是什么意义,不知道,所以不方便他人理解你的程序 另一方面,如果程序中有多处这样的100,一旦程序将来发生更改(假设100要改为1000),那么

  • 软件测试中的可用性、可维护性、可靠性有什么区别?

    软件测试中的可用性、可维护性、可靠性有什么区别?

  • 软件构造——可维护性

    本文是对软件构造课程软件可维护性相关内容的整理与理解,使用的编程语言为 Java。

  • 程序可维护性

    一、概念 1.什么是软件维护 在软件发布后,修改软件以修正错误 和提升性能 维护不只是运维工程师的工作 软件维护不仅仅是运维工程师的工作,而是从设计和开发阶段就开始了 设计和开发者需要考虑软件未来的变化和扩展 设计方案的“easy to change” 这也就是我们说的软件构造的可维护性、可扩展性和灵活性。 面向可维护性的软件构造的例子 模块化、OO设计原则、OO设计模式、基于状态的构造技术、表驱动的构造技术、基于语法的构造技术 软件演化:对软件进行持续的更新 软件的大部分成本来自于维护阶段 软件生命周期中

Global site tag (gtag.js) - Google Analytics