我想使用CSS过渡为SVG元素的位置设置动画。
但是-看起来这对某些SVG元素(例如rect)有效,但不适用于其他SVG元素(例如text):
document.querySelector("button").onclick = function() {
var x = Math.random() * 450;
document.querySelector("rect").setAttributeNS(null, "x", x);
document.querySelector("text").setAttributeNS(null, "x", x);
}
rect {
transition: all 700ms ease-in-out;
}
text {
transition: all 700ms ease-in-out;
}
<svg width="500" height="100">
<rect x="100" y="10" width="30" height="30" fill="blue" stroke="none"/>
<text x="100" y="80" fill="red" stroke="none">Hello</text>
</svg>
<br>
<button>animate</button>
我做错什么了吗?有一个更好的方法吗? (理想情况下,无需使用JavaScript或GreenSock之类的库)。
答案 0 :(得分:3)
您可以改用翻译:
document.querySelector("button").onclick = function() {
var x = Math.random() * 250;
document.querySelector("rect").setAttributeNS(null, "transform","translate("+x+")");
document.querySelector("text").setAttributeNS(null, "transform","translate("+x+")");
}
rect {
transition: all 700ms ease-in-out;
}
text {
transition: all 700ms ease-in-out;
}
<svg width="500" height="100">
<rect x="100" y="10" width="30" height="30" fill="blue" stroke="none"/>
<text x="100" y="80" fill="red" stroke="none">Hello</text>
</svg>
<br>
<button>animate</button>
答案 1 :(得分:2)
正确的解决方案是使用transform
,如Temani所说。
但是,在我的实际应用中-SVG元素正在遮罩下移动,并且该转换似乎会引起意外的副作用。
这是因为对元素的变换也适用于应用于该元素的其他属性。如面膜。解决方法是将遮罩移至父组,以使其不受变换的影响
<g mask="url(#mask1)">
<rect id="rect2" x="0" y="60" width="20" height="20" fill="blue" stroke="none"/>
<text id="text2" x="0" y="100" fill="red" stroke="none">Hello</text>
</g>
完整示例:
document.querySelector("button").onclick = function() {
var x = Math.random() * 450;
/* document.querySelector("rect").setAttributeNS(null, "x", x);
document.querySelector("text").setAttributeNS(null, "x", x);
*/
document.getElementById("rect1").setAttributeNS(null, "x",x);
document.getElementById("text1").setAttributeNS(null, "x",x);
document.getElementById("rect2").setAttributeNS(null, "transform","translate("+x+")");
document.getElementById("text2").setAttributeNS(null, "transform","translate("+x+")");
}
rect {
transition: all 700ms ease-in-out;
}
text {
transition: all 700ms ease-in-out;
}
svg {
border: 1px solid purple;
}
<svg width="500" height="200">
<defs>
<mask id="mask1" x="0" y="0" width="500" height="200">
<rect x="0" y="0" width="200" height="200" fill="#ffffff" stroke="none"/>
</mask>
</defs>
<rect id="rect1" x="0" y="10" width="20" height="20" fill="blue" stroke="none" mask="url(#mask1)"/>
<text id="text1" x="0" y="50" fill="red" stroke="none" mask="url(#mask1)">Hello</text>
<g mask="url(#mask1)">
<rect id="rect2" x="0" y="60" width="20" height="20" fill="blue" stroke="none"/>
<text id="text2" x="0" y="100" fill="red" stroke="none">Hello</text>
</g>
<rect x="0" y="0" width="200" height="200" fill="none" stroke="lime" stroke-width="2"/>
</svg>
<br>
<button>animate</button>
<p>
The green outline shows the position of the mask rect
</p>
答案 2 :(得分:0)
您还可以通过 jquery
实现此目标
$('button').on('click',function(){
var x = Math.random() * 250;
$('rect').attr("transform","translate("+x+")");
$('text').attr("transform","translate("+x+")");
});
rect {
transition: all 700ms ease-in-out;
}
text {
transition: all 700ms ease-in-out;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<svg width="500" height="100">
<rect x="100" y="10" width="30" height="30" fill="blue" stroke="none"/>
<text x="100" y="80" fill="red" stroke="none">Hello</text>
</svg>
<br>
<button>animate</button>