将 GSAP 动画转换为动画 GIF:使用 modern-gif 的分步指南
关键要点
本文将解释如何使用 modern-gif 将使用 GSAP 创建的动画转换为动画 GIF。
以下是一个我之前制作的动画预览:
在下面的链接中,您可以找到本文中将要参考的所有代码的实时预览:
代码库中有两个“页面”。index 包含上面 GIF 的所有代码,simple 是本文中介绍的步骤的起点。
我用来将 GSAP 动画转换为 GIF 的方法涉及在补间的每次“更新”时捕获 SVG 数据并将其写入 HTML 画布。补间完成后,我就可以将 SVG 数据转换为光栅化图像数据,modern-gif 可以使用它来创建动画 GIF 的每一帧。
这是我在简单示例中使用的代码,我将用它来解释从 GSAP 动画创建动画 GIF 所需的每个步骤:
<!DOCTYPE html> <html lang='en'> <head> <meta charset='utf-8' /> <title>Simple</title> </head> <body> <main> <svg id='svg' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 400 200' width={400} height={200} style={{ border: '1px solid red' }} > <rect id='rect' x='0' y='75' width='50' height='50' fill='red'></rect> </svg> <canvas id='canvas' style={{ border: '1px solid blue' }} width={400} height={200}></canvas> <img src="https://img.php.cn/upload/article/000/000/000/173898187373194.jpg" alt="How to Create Animated GIFs from GSAP Animations " /></p> <h2>将 SVG 数据转换为光栅化数据</h2> <pre class="brush:php;toolbar:false"><code class="language-javascript">gsap.timeline({ onUpdate: () => { const xml = new XMLSerializer().serializeToString(svg); const src = `data:image/svg+xml;base64,${btoa(xml)}`; animationFrames.push(src); }, onComplete: () => { let inc = 0; const renderSvgDataToCanvas = () => { const virtualImage = new Image(); virtualImage.src = animationFrames[inc]; virtualImage.onload = () => { ctx.clearRect(0, 0, 400, 200); ctx.drawImage(virtualImage, 0, 0, 400, 200); canvasFrames.push(canvas.toDataURL('image/jpeg')); inc++; if (inc < animationFrames.length) { renderSvgDataToCanvas(); } else { //console.log(canvasFrames); //调试用 generateGif(); } }; }; renderSvgDataToCanvas(); }, }) .fromTo('#rect', { x: -50 }, { duration: 2, x: 350, ease: 'power.ease2' });
此步骤稍微复杂一些,需要对 animationFrames 数组的每个索引执行一个操作。
通过使用递归函数 renderSvgDataToCanvas,我可以使用 animationFrames 数组中的图像数据,将其写入画布。然后,通过使用 canvas.toDataURL('image/jpeg'),我可以将动画每一帧的光栅化数据存储在 canvasFrames 数组中。
如果已在 onComplete 函数中添加 console.log,则应在浏览器控制台中看到类似于以下内容。但是,这次请注意数据的 MIME 类型:它不是 svg xml,而是 image/jpeg。这对于我接下来要做的工作很重要。
这是最后一步,它涉及将 canvasFrames 数组的每个索引传递到 modern-gif。
<!DOCTYPE html> <html lang='en'> <head> <meta charset='utf-8' /> <title>Simple</title> </head> <body> <main> <svg id='svg' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 400 200' width={400} height={200} style={{ border: '1px solid red' }} > <rect id='rect' x='0' y='75' width='50' height='50' fill='red'></rect> </svg> <canvas id='canvas' style={{ border: '1px solid blue' }} width={400} height={200}></canvas> <img src="https://img.php.cn/upload/article/000/000/000/173898187373194.jpg" alt="How to Create Animated GIFs from GSAP Animations " /></p> <h2>将 SVG 数据转换为光栅化数据</h2> <pre class="brush:php;toolbar:false"><code class="language-javascript">gsap.timeline({ onUpdate: () => { const xml = new XMLSerializer().serializeToString(svg); const src = `data:image/svg+xml;base64,${btoa(xml)}`; animationFrames.push(src); }, onComplete: () => { let inc = 0; const renderSvgDataToCanvas = () => { const virtualImage = new Image(); virtualImage.src = animationFrames[inc]; virtualImage.onload = () => { ctx.clearRect(0, 0, 400, 200); ctx.drawImage(virtualImage, 0, 0, 400, 200); canvasFrames.push(canvas.toDataURL('image/jpeg')); inc++; if (inc < animationFrames.length) { renderSvgDataToCanvas(); } else { //console.log(canvasFrames); //调试用 generateGif(); } }; }; renderSvgDataToCanvas(); }, }) .fromTo('#rect', { x: -50 }, { duration: 2, x: 350, ease: 'power.ease2' });
使用 modernGif.encode,您可以将数据数组传递到 frames 并为每一帧定义延迟,我选择添加 0 秒的延迟。
代码的下一部分处理转换 modernGif.ecode 数据并将其转换为“另一个”MIME 类型,这次是 image/gif。
一旦我有了表示动画 GIF 的最终“blob”数据,我就将其转换为 URL,然后设置 image 和 link 元素的 src 和 href,以便我可以在浏览器中查看和下载 GIF。
您可能会注意到最终的 GIF 运行速度相当慢,这是因为在浏览器中运行的动画通常每秒播放 60 帧 (fps),而 GIF 的帧速率通常要慢得多,为 12 或 24 fps。
为了“丢弃”一些动画帧,我使用数组过滤器和 JavaScript 余数运算符来确定索引是否可以被某个数字整除,在我的例子中,我选择 6。不能被 6 整除的索引将从数组中过滤掉。生成的动画 GIF 虽然有点笨拙,但播放速度会快得多。
我已经在 generateGif
函数中添加了 filter
方法来实现帧速率的调整。
就是这样,您可以通过 HTML 画布将 GSAP SVG 动画转换为动画 GIF!
如果您对本文中描述的任何内容有任何疑问,请随时在 Twitter/X 上找到我:@PaulieScanlon。
以上是如何从GSAP动画创建动画GIF的详细内容。更多信息请关注PHP中文网其他相关文章!