调试 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

相关文章

最好用的WPF加载动画功能

《最好用的WPF加载动画功能》当开发应用程序时,提供良好的用户体验(UX)是至关重要的,加载动画作为一种有效的沟通工具,它不仅能告知用户系统正在工作,还能够通过视觉上的吸引力来增强整体用户体验,本文给... 目录前言需求分析高级用法综合案例总结最后前言当开发应用程序时,提供良好的用户体验(UX)是至关重要

基于Python实现PDF动画翻页效果的阅读器

《基于Python实现PDF动画翻页效果的阅读器》在这篇博客中,我们将深入分析一个基于wxPython实现的PDF阅读器程序,该程序支持加载PDF文件并显示页面内容,同时支持页面切换动画效果,文中有详... 目录全部代码代码结构初始化 UI 界面加载 PDF 文件显示 PDF 页面页面切换动画运行效果总结主

React实现原生APP切换效果

《React实现原生APP切换效果》最近需要使用Hybrid的方式开发一个APP,交互和原生APP相似并且需要IM通信,本文给大家介绍了使用React实现原生APP切换效果,文中通过代码示例讲解的非常... 目录背景需求概览技术栈实现步骤根据 react-router-dom 文档配置好路由添加过渡动画使用

使用Vue.js报错:ReferenceError: “Vue is not defined“ 的原因与解决方案

《使用Vue.js报错:ReferenceError:“Vueisnotdefined“的原因与解决方案》在前端开发中,ReferenceError:Vueisnotdefined是一个常见... 目录一、错误描述二、错误成因分析三、解决方案1. 检查 vue.js 的引入方式2. 验证 npm 安装3.

vue如何监听对象或者数组某个属性的变化详解

《vue如何监听对象或者数组某个属性的变化详解》这篇文章主要给大家介绍了关于vue如何监听对象或者数组某个属性的变化,在Vue.js中可以通过watch监听属性变化并动态修改其他属性的值,watch通... 目录前言用watch监听深度监听使用计算属性watch和计算属性的区别在vue 3中使用watchE

python解析HTML并提取span标签中的文本

《python解析HTML并提取span标签中的文本》在网页开发和数据抓取过程中,我们经常需要从HTML页面中提取信息,尤其是span元素中的文本,span标签是一个行内元素,通常用于包装一小段文本或... 目录一、安装相关依赖二、html 页面结构三、使用 BeautifulSoup javascript

Qt QWidget实现图片旋转动画

《QtQWidget实现图片旋转动画》这篇文章主要为大家详细介绍了如何使用了Qt和QWidget实现图片旋转动画效果,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 一、效果展示二、源码分享本例程通过QGraphicsView实现svg格式图片旋转。.hpjavascript

Vue3 的 shallowRef 和 shallowReactive:优化性能

大家对 Vue3 的 ref 和 reactive 都很熟悉,那么对 shallowRef 和 shallowReactive 是否了解呢? 在编程和数据结构中,“shallow”(浅层)通常指对数据结构的最外层进行操作,而不递归地处理其内部或嵌套的数据。这种处理方式关注的是数据结构的第一层属性或元素,而忽略更深层次的嵌套内容。 1. 浅层与深层的对比 1.1 浅层(Shallow) 定义

这15个Vue指令,让你的项目开发爽到爆

1. V-Hotkey 仓库地址: github.com/Dafrok/v-ho… Demo: 戳这里 https://dafrok.github.io/v-hotkey 安装: npm install --save v-hotkey 这个指令可以给组件绑定一个或多个快捷键。你想要通过按下 Escape 键后隐藏某个组件,按住 Control 和回车键再显示它吗?小菜一碟: <template