调试 CSS Keyframe 动画

2023-12-02 20:20

本文主要是介绍调试 CSS Keyframe 动画,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

学会语法就可以制作 CSS 动画,但是要想做出动感、美观的动画,仅会语法是不够的。动画直接关系到用户体验,因此我们需要改进代码,从而找到正确的触发时机并掌握调试动画的方法。经过一番研究之后,我总结了一些有用的工具和方法。

使用负的延迟值

如果你需要同时执行多个动画并错开它们的开始时间,可以使用animation-delay。但是这会导致用户打开网页时有些元素需要静止一段时间才会开始移动。

此时可以给animation-delay设置一个负数,这样会将播放头向前移动,因此用户打开网页的时候所有动画都会播放。使用这种方式可以通过共享一套 keyframes 来实现不同的动画。

这个技巧也可以用来调试。设置animation-play-state: paused;然后把延迟设置成不同的负数,就可以看到动画在不同帧的状态。

.thing {animation: move 2s linear infinite alternate;animation-play-state: paused;animation-delay: -1s;
}

示例:

http://codepen.io/css-tricks/embed/LVMMGZ

在下面这个有趣的例子中,可以看到两个机器人的动作错开了一点时间,这样看起来会更自然。我们给粉色的机器人设置一个负的延迟,这样用户打开网页的时候他就已经处在移动状态了。

.teal {animation: hover 2s ease-in-out infinite both;
}.purple {animation: hover 2s -0.5s>http://www.0771ybyy.com/case/zhichuangjibing/1775.html< ease-in-out infinite both;
}@keyframes hover {50% {transform: translateY(-4px);}
}

示例:http://codepen.io/sdras/embed/qdLJLJ

多 transform 之殇

为了充分提高性能,你需要尽可能多地使用transform来移动和改变元素,这样就会减少修改margintop/left之类属性带来的重绘损耗。Paul Lewis维护的CSS Triggers非常棒,可以直观地看出这些属性对应的损耗。然而,如果你使用多个 transform 来移动元素,就可能带来一系列问题。

第一个问题是顺序。Transform 并不像你想的那样同步发生,而是按照一定顺序。最右边的操作最先执行,然后往左依次执行。举例来说,下面的代码中scale首先执行,然后是translate,最后是rotate

@keyframes foo {to {/*         3rd           2nd              1st      */transform: rotate(90deg) >http://www.0771ybyy.com/zc/1795.html<translateX(30px) scale(1.5);}
}

大多数情况下这不是我们想要的,通常我们希望这些操作同时发生。此外,如果你把 transform 分割成多个 keyframe,事情会变得更加复杂,有些操作同步,有些操作不同步。比如下面这个例子:

@keyframes foo {30% {transform: rotateY(360deg);}65% {transform: translateY(-30px) rotateY(-360deg) scale(1.5);}90% {transform: >http://www.0771ybyy.com/zc/1794.html<translateY(10px) scale(0.75);}
}

这段代码会产生非常糟糕的效果。不幸的是,解决方法并不优雅,通常你必须嵌套多个<div>,每个应用一个变化,这样就不会产生冲突。

http://codepen.io/sdras/embed/bdOvJL

还有一些解决方法,比如使用矩阵变换(通常无法手写)或者使用 JavaScript 的动画 API(比如GreenSock),这样就可以同步执行多个变换操作。

使用多个 div 还可以解决 SVG 的一些 bug。在 Safari 中,不能同时声明 opacity 和 transform 动画——其中一个会失败。你可以查看本文的第一个例子。

在 2015 年 8 月初,Chrome Canary 支持独立 transform 声明。这意味着我们不再需要关心执行顺序,你可以分别声明rotatetranslatescale

调试工具

Chrome和Firefox都提供了调试动画的工具。这些工具提供了控制速度的滑块、暂停按钮以及 easing 值对应的 UI。对于调试 CSS 动画来说,减速并检查特殊位置的动画效果真的非常有用。

这些工具都使用了 Lea Verou 的cubic-bezier.com可视化工具和 GUI。这样你就可以直接进行调试,不用每次都跑到网站上输入文本。

这些工具可以帮助我们细粒度地调整动画,下面是两个工具的 UI:

Chrome 和 Firefox 都可以控制时间(加速或者减速),也可以手动执行动画。Chrome 正在开发许多高级的时间线工具,可以用它们同时调试多个元素。这是件好事,每次只能调试一个元素确实是个很大的限制。

我遇到的一个问题是,如果元素的动画时间很短,那就很难及时获取这个元素。我的解决方案是设置animation-iteration-count: infinite;,这样就不需要和时间赛跑。

此外,我发现减速、重播以及调整时间非常有用,你可以在很低的层面观察动画到底是如何执行的。如果你在低速下调整好动画,恢复到正常速度之后动画会变得非常棒。

使用 JavaScript 调试 CSS 动画事件

如果你想知道每个动画触发的准确时间和位置,可以使用 JavaScript 来监听animationstartanimationiterationanimationend事件并输出信息。

看下面这个例子:

http://codepen.io/sdras/embed/PqXeMX

保证 keyframe 足够准确

我经常看到有人在 0% 和 100% keyframe中声明相同的属性和值。没必要这样做,浏览器会在动画开始和结束时自动处理属性值。

如下所示:

.element {animation: >http://www.0771ybyy.com/sunshang/1788.html<animation-name 2s linear infinite;
}@keyframes animation-name {0% {transform:>http://www.0771ybyy.com/zc/1793.html< translateX(200px);}50% {transform: translateX(350px);}100% {transform: translateX(200px);}
}

可以改写成:

.element {transform: translateX(200px);animation: >http://www.0771ybyy.com/zc/1792.html<animation-name 2s linear infinite;
}@keyframes animation-name {50% {transform: translateX(350px);}
}

让动画也 DRY

漂亮和简洁的动画通常意味着一个特殊的cubic-bezier()easing 函数。仔细调整过的 easing 函数会成为公司的一个特点。动画会传递公司的品牌和“声音”。如果你在网站中大量使用这个函数,最简单(并且最一致)的方法就是把函数保存到变量中,我们就是这么做的。SASS 或者其他预/后处理器都可以做到这一点:

$smooth: cubic-bezier(0.17, 0.67, 0.48, 1.28);.foo { animation: >http://www.0771ybyy.com/zc/1791.html<animation-name 3s $smooth; }.bar { animation: animation-name 1s $smooth; }

如果使用 CSS keyframe 编写动画,我们需要尽量利用 GPU。这意味着如果你需要操作多个对象,就需要提前准备好 DOM 并给元素分层。使用标准的 CSS 声明代码块可以让硬件加速原生 DOM 元素(SVG 不行)。由于我们需要复用代码块,把它存储到 mixin 或者 extend 中是个不错的选择:

@mixin accelerate($name) {will-change: $name;transform: translateZ(0);backface-visibility: hidden;perspective: >http://www.0771ybyy.com/zc/1790.html<1000px;
}.foo {@include accelerate(transform);
}

一定要小心,同时操作多个元素可能会引发副作用并严重降低性能。大多数动画都没有问题,不过如果你使用类似 haml 的技术来生成多个 DOM 元素,那就要小心了。

使用循环提高性能

Smashing Magazine 最近发布的一篇文章中详细介绍了Species in Pices项目的原理。在其中的一节里,作者解释了为什么同时操作大量对象会导致性能问题。他说:

假设你要同时移动 30 个对象;你需要浏览器做很多工作,因此会导致问题。如果你的动画速度是 0.199 秒并且每个对象都延迟 0.2 秒,那同时只会操作一个对象,从而解决问题。虽然总的动画次数不变,但是因为动画现在变成了一个连续执行的序列,性能可以提高 30 倍。

可以使用 Sass 或者其他预/后处理器的for循环来编写这样的代码。下面是我写的一个简单的例子:

@for $i from 1 through $n {&:nth-child(#{$i}) {animation: loadIn >http://www.0771ybyy.com/sunshang/1789.html<2s #{$i*0.11}s $easeOutSine forwards;}
}

这不仅会错开动画,还可以错开其他的视觉效果,比如颜色改变。(点击 rerun 来重播动画。)

示例:http://codepen.io/sdras/embed/RPEMZr

调整动画顺序

编写很长的动画时,常用的办法是把它们写成一个序列并加上延迟,比如:

animation: foo 3s ease-in-out, bar 4s 3s ease-in-out, brainz 6s 7s ease-in-out;

但是假设你现在要重构代码,需要修改第一个动画的时间,这会导致后续的动画都需要修改时间。这也不是什么大事:

animation: foo 2.5s ease-in-out, bar 4s 2.5s ease-in-out, brainz 6s 6.5s ease-in-out;

不过假设我们需要添加一个新动画并再次调整时间(在实际项目中类似的改动经常发生),就会发现这种修改方式非常低效。如果你做过 3 次以上,就会明白,这真的很低效。

继续,假设动画执行到一半的时候有两个改动需要同时出发,所以你需要保证两个不同的属性一致然后……好的,你应该懂了。这就是为什么处理超过三个串联动画时我会使用 JavaScript 的原因。就我自己来说,我喜欢使用GreenSock 动画 API,因为它的时间线功能非常好用,而且不需要重新计算就能轻松重叠多个动画,这可以极大地提升效率。

改进动画远比编写难。通常来说,需要不断编辑、修改和调试才能提高项目的质量和性能。希望这些技巧可以帮助你更好地编写动画。

这篇关于调试 CSS Keyframe 动画的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/446683

相关文章

Vue3组件中getCurrentInstance()获取App实例,但是返回null的解决方案

《Vue3组件中getCurrentInstance()获取App实例,但是返回null的解决方案》:本文主要介绍Vue3组件中getCurrentInstance()获取App实例,但是返回nu... 目录vue3组件中getCurrentInstajavascriptnce()获取App实例,但是返回n

JS+HTML实现在线图片水印添加工具

《JS+HTML实现在线图片水印添加工具》在社交媒体和内容创作日益频繁的今天,如何保护原创内容、展示品牌身份成了一个不得不面对的问题,本文将实现一个完全基于HTML+CSS构建的现代化图片水印在线工具... 目录概述功能亮点使用方法技术解析延伸思考运行效果项目源码下载总结概述在社交媒体和内容创作日益频繁的

前端CSS Grid 布局示例详解

《前端CSSGrid布局示例详解》CSSGrid是一种二维布局系统,可以同时控制行和列,相比Flex(一维布局),更适合用在整体页面布局或复杂模块结构中,:本文主要介绍前端CSSGri... 目录css Grid 布局详解(通俗易懂版)一、概述二、基础概念三、创建 Grid 容器四、定义网格行和列五、设置行

前端下载文件时如何后端返回的文件流一些常见方法

《前端下载文件时如何后端返回的文件流一些常见方法》:本文主要介绍前端下载文件时如何后端返回的文件流一些常见方法,包括使用Blob和URL.createObjectURL创建下载链接,以及处理带有C... 目录1. 使用 Blob 和 URL.createObjectURL 创建下载链接例子:使用 Blob

Vuex Actions多参数传递的解决方案

《VuexActions多参数传递的解决方案》在Vuex中,actions的设计默认只支持单个参数传递,这有时会限制我们的使用场景,下面我将详细介绍几种处理多参数传递的解决方案,从基础到高级,... 目录一、对象封装法(推荐)二、参数解构法三、柯里化函数法四、Payload 工厂函数五、TypeScript

Vue3使用router,params传参为空问题

《Vue3使用router,params传参为空问题》:本文主要介绍Vue3使用router,params传参为空问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐... 目录vue3使用China编程router,params传参为空1.使用query方式传参2.使用 Histo

使用Python自建轻量级的HTTP调试工具

《使用Python自建轻量级的HTTP调试工具》这篇文章主要为大家详细介绍了如何使用Python自建一个轻量级的HTTP调试工具,文中的示例代码讲解详细,感兴趣的小伙伴可以参考一下... 目录一、为什么需要自建工具二、核心功能设计三、技术选型四、分步实现五、进阶优化技巧六、使用示例七、性能对比八、扩展方向建

CSS Padding 和 Margin 区别全解析

《CSSPadding和Margin区别全解析》CSS中的padding和margin是两个非常基础且重要的属性,它们用于控制元素周围的空白区域,本文将详细介绍padding和... 目录css Padding 和 Margin 全解析1. Padding: 内边距2. Margin: 外边距3. Padd

CSS will-change 属性示例详解

《CSSwill-change属性示例详解》will-change是一个CSS属性,用于告诉浏览器某个元素在未来可能会发生哪些变化,本文给大家介绍CSSwill-change属性详解,感... will-change 是一个 css 属性,用于告诉浏览器某个元素在未来可能会发生哪些变化。这可以帮助浏览器优化

CSS去除a标签的下划线的几种方法

《CSS去除a标签的下划线的几种方法》本文给大家分享在CSS中,去除a标签(超链接)的下划线的几种方法,本文给大家介绍的非常详细,感兴趣的朋友一起看看吧... 在 css 中,去除a标签(超链接)的下划线主要有以下几种方法:使用text-decoration属性通用选择器设置:使用a标签选择器,将tex