我无法使用img
标记为我导入的svg设置动画。我无法对svg进行硬编码,因为我的项目在使用webpack进行预处理时会生成它。遗憾的是,我似乎无法通过svg
标记获取文件,因为我不知道任何" src"或" href"属性。
如何为没有硬编码的SVG设置动画?
答案 0 :(得分:2)
这实际上取决于如何你的动画。
基本上有三种方法可以生成动画SVG:
在<svg>
代码中嵌入<img>
documentElement时,这些行为如何表现?
<img>
中的SMIL动画。在支持浏览器时,这些浏览器会正常运行,就好像你的SVG没有嵌入一样 您将面临的唯一限制是
element.click
相同的事件无法正常工作这两个限制都不会影响<object>
,<embed>
或<iframe>
中加载的SVG,因此您可以在需要时使用它。
var svgStr = `
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 50 50" width="50" height="50">
<rect id="rect" x="-30" y="0" width="30" height="50">
<!-- this will work normally, even in an <img> -->
<animate attributeType="XML" attributeName="x" from="-30" to="50"
begin="0s" dur="10s" repeatCount="indefinite"/>
<!-- this will not work in <img>, but will in <object>/<iframe>/<embed> -->
<animate attributeType="XML" attributeName="fill" from="blue" to="red"
begin="rect.click"
dur="1s" repeatCount="1"/>
</rect>
<!-- js-based workaround won't work in <img> but will in <object>/<iframe>/<embed> -->
<script src="https://cdn.rawgit.com/FakeSmile/FakeSmile/23c5ceae/smil.user.js"><\/script>
</svg>`;
loadSVG(document.images[0]);
loadSVG(document.querySelector('object'));
function loadSVG(container) {
var url = URL.createObjectURL(new Blob([svgStr], {type: 'image/svg+xml'}));
container.src = container.data = url;
}
&#13;
img{
border: 1px solid green;
}
object{
border: 1px solid blue;
}
&#13;
<img src="">
<object></object>
<div>Try to click the black rectangle in both the <code><img></code> and <code><object></code> tags.
&#13;
<img>
中的CSS动画。就像SMIL动画一样,它们应该支持浏览器,具有相同的用户手势限制,以及相同的可能方式(使用其他容器):
var svgStr = `
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 50 50" width="50" height="50">
<rect id="rect" x="0" y="0" width="30" height="50"/>
<defs>
<style>
#rect {
/* this will work normally, even in an img */
animation: move 10s linear infinite;
}
#rect:hover {
/* this will not work in img, but will in object/iframe/embed */
animation: move 10s linear infinite, color 1s 1;
}
@keyframes move {
from {
transform: translate(-30px, 0px);
}
to {
transform: translate(50px, 0px);
}
}
@keyframes color {
from {
fill: blue;
}
to {
fill: red;
}
}
</style>
</defs>
</svg>`;
loadSVG(document.images[0]);
loadSVG(document.querySelector('object'));
function loadSVG(container) {
var url = URL.createObjectURL(new Blob([svgStr], {type: 'image/svg+xml'}));
container.src = container.data = url;
}
&#13;
img{
border: 1px solid green;
}
object{
border: 1px solid blue;
}
&#13;
<img src="">
<object></object>
<div>Try to mouse hover the black rectangle in both the <code><img></code> and <code><object></code> tags.
&#13;
<img>
中基于脚本的动画。这些根本行不通。嵌入在<img>
标记中的SVG文档无法编写脚本。
要解决此问题,请使用<object>
,<embed>
或<iframe>
元素作为容器。
var svgStr = `
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 50 50" width="50" height="50">
<rect id="rect" x="0" y="0" width="30" height="50"/>
<script type="application/javascript">
// will simply never work in img
var x = 0, rect = document.getElementById('rect');
function anim() {
x = (x + 1) % 80;
rect.setAttribute('x', x - 30);
requestAnimationFrame(anim);
}
anim();
<\/script>
</svg>`;
loadSVG(document.images[0]);
loadSVG(document.querySelector('object'));
function loadSVG(container) {
var url = URL.createObjectURL(new Blob([svgStr], {type: 'image/svg+xml'}));
container.src = container.data = url;
}
&#13;
img{
border: 1px solid green;
}
object{
border: 1px solid blue;
}
&#13;
<img src="">
<object></object>
&#13;
所以基本上,<img>
中的SVG有很多限制,使用其他容器都会让人不知所措。
现在,每个容器都有自己的限制:
<iframe>
不会调整其内容大小,默认情况下也会带边框和其他一些丑陋的东西。 <object>
和<embed>
将在不可见(display: none
)时被webkit浏览器卸载,并且不会在任何浏览器中缓存... 当然,还可以通过AJAX获取SVG标记并将其加载到实际的HTML页面中,但我个人不建议这样做:
由于我们在这里,<img>
中SVG的另一个限制是它无法在自己的标记之外加载任何资源,所有内容都需要直接包含在其中,甚至是字体和光栅图像