我有一个过渡动画,我想在group元素内的SVG元素的宽度上触发。该动画似乎只能在Chrome浏览器上运行。
<!-- works -->
<svg width="400" height="100">
<rect id="rect-1" width="400" height="100" style="fill:rgb(0,0,255);stroke-width:3;stroke:rgb(0,0,0)" />
</svg>
<!-- only works in Chrome -->
<svg width="400" height="400">
<defs>
<g id="my-rect">
<rect id="rect-2" width="400" height="100" style="fill:rgb(0,0,255);stroke-width:3;stroke:rgb(0,0,0)" />
</g>
</defs>
<use xlink:href="#my-rect" y="0"/>
<use xlink:href="#my-rect" y="110"/>
</svg>
.grow {
-webkit-transition: 1.5s;
-moz-transition: 1.5s;
-o-transition: 1.5s;
transition: 3s;
width: 10px;
}
(() => {
setTimeout(() => {
const rect1 = document.getElementById('rect-1');
rect1.classList.add('grow');
const rect2 = document.getElementById('rect-2');
rect2.classList.add('grow');
}, 1000);
})();
要复制,请在Safari或Firefox中打开此fiddle。 您将看到第二个矩形的过渡无法正常工作。
是否有任何变通方法来使SVG组中特定元素的过渡动画正常工作?
答案 0 :(得分:2)
该元素从SVG文档中获取节点,并且 将它们复制到其他地方。 -mdn
因此不必使用use
,因为您不必复制它。
(() => {
setTimeout(() => {
const rect1 = document.getElementById('rect-1');
rect1.classList.add('grow');
const rect2 = document.getElementById('rect-2');
rect2.classList.add('grow');
}, 1000);
})();
.grow {
-webkit-transition: 1.5s;
-moz-transition: 1.5s;
-o-transition: 1.5s;
transition: width 3s;
width: 10px;
}
<!-- works -->
<svg width="400" height="100">
<rect id="rect-1" width="400" height="100" style="fill:rgb(0,0,255);stroke-width:3;stroke:rgb(0,0,0)" />
</svg>
<svg width="400" height="100">
<rect id="rect-2" width="400" height="100" style="fill:rgb(0,0,255);stroke-width:3;stroke:rgb(0,0,0)" />
</svg>
当元素重复时,即使SVG <animate>
在FireFox中也不起作用。虽然如果未在刷新的元素内使用。这是一个已知的问题。关于堆栈溢出,有多个未解决的问题,例如this one。
<!-- Learn about this code on MDN: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/use -->
<svg viewBox="0 0 30 10" xmlns="http://www.w3.org/2000/svg">
<circle id="myCircle" cx="5" cy="5" r="4" stroke="blue"/>
<use href="#myCircle" x="10" fill="blue"/>
<use href="#myCircle" x="20" fill="white" stroke="red"/>
<!--
stroke="red" will be ignored here, as stroke was already set on myCircle.
Most attributes (except for x, y, width, height and (xlink:)href)
do not override those set in the ancestor.
That's why the circles have different x positions, but the same stroke value.
-->
<animate
xlink:href="#myCircle"
attributeName="r"
from="4"
to="2"
dur="5s"
begin="0s"
repeatCount="1"
fill="freeze"
id="circ-anim"/>
</svg>
被引用元素上的动画会导致实例也被动画化。 use - w3
对于每个文档,如果您为刷新的元素(`myCircle)设置动画,则也应该对所有重复元素进行动画处理。因此,我想这是一个错误,无法在Firefox和Safari中使用。
使用svg <animate>
标签并将其包含在<rect>
中。
<svg width="400" height="400">
<defs>
<g id="my-rect">
<rect id="rect-2" width="400" height="100" style="fill:rgb(0,0,255);stroke-width:3;stroke:rgb(0,0,0)">
<animate
attributeName="width"
from="400"
to="10"
dur="3s"
begin="1s"
repeatCount="1"
fill="freeze"
id="rect-2"/>
</rect>
</g>
</defs>
<use xlink:href="#my-rect" y="0"/>
<use xlink:href="#my-rect" y="110"/>
</svg>
答案 1 :(得分:1)
如何将动画标签嵌套在圆内?
<svg width="400" height="350">
<rect id="my-rect" width="400" height="100" style="fill:rgb(0,0,255);stroke-width:3;stroke:rgb(0,0,0)">
<animate
attributeName="width"
from="0"
to="400"
dur="5s"
begin="0s"
repeatCount="1"
fill="freeze"
id="rect-anim"/>
</rect>
<use xlink:href="#my-rect" y="110"/>
<use xlink:href="#my-rect" y="220"/>
</svg>
答案 2 :(得分:0)
总结来说,一种解决方法是退回到SMIL SVG动画而不使用CSS。
请参阅针对我的原始问题改编的fiddle。
<svg width="400" height="100">
<rect id="rect-1" width="400" height="100" style="fill:rgb(0,0,255);stroke-width:3;stroke:rgb(0,0,0)" />
</svg>
<svg width="400" height="400">
<defs>
<g id="my-rect">
<rect id="g-rect" width="400" height="100" style="fill:rgb(0,0,255);stroke-width:3;stroke:rgb(0,0,0)"/>
</g>
</defs>
<use xlink:href="#my-rect" y="0"/>
<use xlink:href="#my-rect" y="110"/>
</svg>
(() => {
setTimeout(() => {
const rect1 = document.getElementById('rect-1');
rect1.classList.add('grow');
const groupRect = document.getElementById('g-rect');
const growAnimation = document.createElementNS('http://www.w3.org/2000/svg', 'animate')
growAnimation.setAttribute('attributeName', 'width');
growAnimation.setAttribute('from', '400');
growAnimation.setAttribute('to', '10');
growAnimation.setAttribute('dur', '3s');
growAnimation.setAttribute('fill', 'freeze');
growAnimation.setAttribute('begin', 'indefinite');
groupRect.appendChild(growAnimation);
growAnimation.beginElement();
}, 1000);
})();