重启背景SVG动画

Posted

技术标签:

【中文标题】重启背景SVG动画【英文标题】:Restart background SVG animation 【发布时间】:2013-10-11 05:40:20 【问题描述】:

我将 SVG 设置为元素的背景图像。第一次显示元素时,动画正确播放。

在随后的显示中(例如,如果通过 javascript 注入元素的副本,或者如果背景图像被移除并使用 CSS/JavaScript 添加回来),动画不会从头开始。我认为这是预期的功能,因为图像不被认为已被浏览器重新加载 - 它使用已经动画的内存版本。

这是一个演示(不是我的): http://www.luigifab.info/public/svg-smil/test.html

Firefox 和 Chrome 有一些相关的浏览器错误报告,但如上所述,我认为这是预期的功能。

有什么方法可以让我的 SVG 动画在图像显示时重置/重放?

理想情况下,我正在寻找仅使用 CSS 和 SVG 的解决方案 - 如果不可能,则使用 JavaScript 解决方案。

【问题讨论】:

您的 SVG 图像显示不正确..?那是问题呃..?.. SVG 正在显示,它们只是在随后的显示中没有动画。如果您单击上面的演示链接,然后点击“显示”,您将看到 SVG 动画。再次单击“隐藏”然后“显示”,SVG 不会动画。 你能告诉我你的 Animate 代码吗? 使用的是SVG动画,代码与上面demo链接中使用的SVG类似:luigifab.info/public/svg-smil/error.svg.php 【参考方案1】:

正如@netsurfer 所说,我通过使用object 解决了这个问题。这是一个例子:

<object type="image/svg+xml" data="my.svg"></object>

每次我动态注入 SVG object 时,动画都会从头开始。

【讨论】:

所以你用这个&lt;object&gt;作为绝对定位的背景? M V P - 像魅力一样工作?【参考方案2】:

我认为您的猜测“......因为图像不被认为已被浏览器重新加载 - 它使用已经动画的内存版本”是正确的,因为 SVG 文件已被缓存!因此,如果没有(真正的)“重新加载”,则不会(再次)触发动画。

好吧,首先让我们看一下 SVG 动画。您可以在动画元素中使用两个属性来重复动画 - 请参阅 Repeating Animations 和 The ‘animate’ element。在您的情况下,动画只运行一次(不重复)。

因此,您需要 Javascript 以某种方式“触发”动画。 原则上这是可能的(例如:Advanced SVG Animation Techniques),但前提是 SVG 文件是 DOM 的一部分,您可以通过 Javascript 访问它。因此,您必须将 SVG 文件包含为 &lt;object&gt;

只要您在 &lt;img&gt; 标记或 CSS background-image 中使用 SVG 文件,您就无法通过脚本访问该文件。

所以我能想到的实现目标的唯一方法是阻止浏览器缓存 SVG 文件(请参阅 How (and how not) to Control Caches),或者在 &lt;object&gt; 元素中使用 SVG 文件,以便您可以控制通过 Javascript 制作动画。

顺便说一句:luigifab 的回答还不错。这是强制重新加载文件/图像的常用“技巧” - 请参阅The Cache Trick

【讨论】:

【参考方案3】:

一种可能性是更改图像 URL 以强制浏览器重新加载。

【讨论】:

每次有人访问页面时更改它!?【参考方案4】:

luigifab 答案的实现。在 url 参数末尾添加一些 random things,这将迫使浏览器认为该资源是“新资源”。 Demo

【讨论】:

【参考方案5】:

这对我有用, 只需通过将 setTimeout 添加到延迟 classList.add('play') 来向 div 元素添加和删除“播放”类,以便可以删除然后应用该类

CSS

@keyframes play60 
        0% 
            background-position: 0px 0px;
        
        100% 
            background-position: -38400px 0px;
        
    
    .shapeshifter 
        animation-duration: 1000ms;
        animation-timing-function: steps(60);
        animation-fill-mode: forwards;
        width: 640px;
        height: 640px;
        background-repeat: no-repeat;
    
    .shapeshifter.play 
        animation-name: play60;
    

JS:

document.getElementById('shape').addEventListener('mouseover', () => 
    document.getElementById('shape').classList.remove('play')
    setTimeout(() => 
        document.getElementById('shape').classList.add('play');
    , 1)
)

HTML

<div class="shapeshifter " id="shape" style="background-image: url(shape.svg)"></div>

【讨论】:

【参考方案6】:

在 url 中使用随机键进行缓存清除。 尽管您的示例没有很长的动画来正确测试它,但我添加了重复加载图像以使差异明显。

url + "&amp;" + Math.random()

没有使用恒定 URL 的重新加载演示:http://jsfiddle.net/4ZBLr/8/

使用随机 URL src 重新加载演示:http://jsfiddle.net/4ZBLr/9/

【讨论】:

2020 年,&amp; 似乎破坏了 Chrome 和 FF 中的图像链接。改用#? 似乎可行。【参考方案7】:

我认为在许多情况下setCurrentTime(0) 是最好的解决方案——如果浏览器支持的话。这是一个示例(当然,假设您使用&lt;object&gt; 标签进行嵌入):

let content = document.getElementById("object-id").contentDocument;
let svg = content.getElementsByTagName("svg")[0];
if(svg.getCurrentTime() > 10)
  svg.setCurrentTime(0);

有关相关 API 的更多信息可以在这里找到: https://developer.mozilla.org/en-US/docs/Web/API/SVGSVGElement

【讨论】:

以上是关于重启背景SVG动画的主要内容,如果未能解决你的问题,请参考以下文章

SVG 动画图案边缘

在链接悬停时为 SVG 设置动画

滑块的 CSS SVG 动画

CSS3 SVG实现可爱的动物哈士奇和狐狸动画

如何将 svg 路径变形动画合并到 React 应用程序中

svg动画类库Snap.svg简介