Web Animation 网页动画Last updated: 2023-05-06IntroductionSlides CC BY-NC 4.0 feedback Web Animation 网页动画 什么是动画? 网页动画简史 网页动画技术 网页动画的工作原理 Framer Motion 简介 1. 什么是动画? 动画 通过定时拍摄多个静止的固态图像(帧),以一定频率连续变化而导致肉眼的视觉残象产生错觉,而误以为图像或物体活动的技术。 视觉暂留 光对视网膜所产生的视觉,在光停止作用后,仍然保留一段时间的现象。原因是由视神经的反应速度造成的,其时值约是 1/16 秒,对于不同频率的光有不同的暂留时间。是现代影视、动画等视觉媒体制作和传播的根据。 从史前文明到如今的信息时代,在人类文化中几乎都贯穿着动画的身影。现在,我们特别关注关于前端的动画: Web Animation 网页动画 2. 网页动画简史 有史以来创建的第一个网站的样子,当时甚至缺少 CSS。 Netscape Navigator 于 1995 年支持了 GIF 在浏览器中的使用。 90 年代后期,Flash 被发明并被逐渐使用,随后十几年 Flash 在网络上成为流行的动画实现方式。 在 2010 年的 4 月,苹果公司的 CEO 乔布斯发表一篇题为“对 Flash 的思考”的文章,指出随着 HTML5 的发展,观看视频或其它内容时,Adobe Flash 将不再是必须的。 iOS 不支持 Flash 的真实原因是什么? 2014 年 10 月 28 日,W3C 正式发布 HTML5 推荐标准。 CSS3 标准自 1999 年开始制定,采用了模块化的规范制定方式。在 2009 年发布了与动画相关的 animations 和 transform 模块公开草案。 移动互联网的快速发展 HTML/CSS/JavaScript 规范对新特性的支持逐渐完善 Flash 慢性死亡 使用前端技术开发网页动画逐渐成为主要开发方式 3. 网页动画技术 CSS JavaScript WebGL(WebGPU) CSS Animations transition .ele { transition: opacity 4s ease-in-out; opacity: 0.5; } .ele:hover { opacity: 1; } animation .ele { animation: 4s linear 0s infinite alternate move; } @keyframes move { from { margin-left: -20%; } to { margin-left: 100%; } } .pause { animation-play-state: paused; } .active { animation-play-state: running; } 贝塞尔曲线 CSS 中的cubic-bezier() 由 4 个控制点构成。并且默认第 1 个和第 4 个固定坐标为 (0, 0) 和 (1, 1)。cubic-bezier(x2, y2, x3, y3) 定义的是第 2、3 个控制点的坐标。 JavaScript Animations setInterval/setTimeout setInterval(function () { // change element style ele.style.left = left + 5 + 'px' }, 16) requestAnimationFrame Web Animations API (WAAPI) requestAnimationFrame requestAnimationFrame(callback: (time: number) => void) function step() { if (ele.style.left < 200) { // set element style ele.style.left = left + 5 + 'px' requestAnimationFrame(step) } } requestAnimationFrame(step) Web Animations API JavaScript 将最新的动画支持称为 Web Animations API (WAAPI)。 Using the Web Animations API const cake = document.getElementById('#cake') const animateCake = cake.animate( [{ transform: 'translateY(0)' }, { transform: 'translateY(-80%)' }], { easing: 'steps(4, end)', duration: aliceChange.effect.timing.duration / 2, }, ) // 开始/暂停 animateCake.pause() animateCake.play() // 结束/中断 animateCake.cancel() animateCake.finish() animateCake.reverse() // 调整速率 animateCake.playbackRate *= 1.1 // ... CSS 与 JavaScript 的性能差异 根据MDN - CSS 动画与 JavaScript 动画的性能的结论 事实上,大多数场景下,基于 CSS 的动画几乎是跟 JavaScript 动画表现一致。一些基于 Javascript 的动画库,甚至声称他们在性能上可以做得比原生 CSS 更好。 这是可能的,因为在重绘事件发生之前,CSS transition 和 animation 在 UI 线程仅仅是重新采集元素的样式,这跟通过 requestAnimationFrame() 回调获取重新采集元素样式是一样的,也是在下一次重绘之前触发。假如二者都是在主 UI 线程创建的动画,那它们在性能方面没有差异。 CSS 动画更适合简单无需复杂控制的动画场景 JavaScript 更适合需要对动画进行控制,如调整动画速率、调整动画时序等动画场景 第三方动画库借助 JavaScript 可以实现更强大的动画能力 4. 网页动画的工作原理 定义动画始终需要定义两个基本状态,即开始和结束状态。通过计算插值状态,实现动画效果。 Progression = f(Time) 例如 线性: f = (x) => x 速率从 0 开始的 n 次幂加速: f = (x) => Math.pow(x, n) 访问 ts-easing 查看一些常见的插值动画函数 animate function animate(callback, duration = 2500, f = easing.ease) { let start = performance.now() const loop = time => { // progression 从 0 增加到 1 let progression = (time - start) / duration if (progression > 1) progression = 1 // 计算当前动画状态 let progress = f(progression) callback(progress) // 绘制 if (progression < 1) { requestAnimationFrame(loop) } } requestAnimationFrame(loop) } Framer Motion react-spring framer-motion gsap matter.js ... Framer Motion 基本概念 Framer Motion 是一个 React 动画库,它提供了一系列支持动画的基础组件、事件方法及 hooks 方法供开发者方便快捷地实现动画效果。 <motion.div animate={{ x: 100 }} whileTap={{ y: 10 }} /> motion 支持动画效果的组件,支持定义动画帧,支持通过 transition 定义过渡效果。 whileTap whileHover 等支持动画效果的方法。 variants 支持在多个不同的动画帧状态之间切换。 layout 支持布局动画。 Layout Animation <div className="flex"> <motion.div layout style={{ justifySelf: position }}></motion.div> </div> LayoutId 通过 LayoutId 可以将不同的组件进行关联,从而实现在非同一个页面元素实现动画切换的效果。 Introducting FLIP First: ele.getBoundingClientRect() 获取初始位置 {x: 0} Last: 获取终点位置 {x: 10} Inverse: 此时已经有了起始点的信息,计算终点状态反转到初始状态需要的转换参数 {transform: translateX(-10)} Play: 将第三步的转换参数归零,并添加动画过渡效果 translateX(-10) -> translateX(0) 总结 网页动画经历了很多年的发展,最终形成了通过 CSS,JavaScript 编写动画的主流方式。 CSS 通过定义动画帧可以快速的实现简单的动画。 开发者可以通过 window.requestAnimationFrame 方法使用 JavaScript 开发高性能的动画效果。同时也有原生的 Web Animations API 可供选择使用,但目前仍需要考虑兼容性问题。 React 开发者可以通过优秀的第三方库如 framer motion 简单快速的构建动画效果。 参考 The History of Web Animation. How Web Animation Works. Cubic Bézier: from math to motion Guide to creating animations that spark joy with Framer Motion Everything about Framer Motion layout animations Inside Framer's Magic Motion