用JavaScript动画SVG背景

时间:2018-12-26 11:15:01

标签: javascript css svg jquery-animate

我正在使用js添加svg背景,并使用设置的间隔为其设置动画效果。这在chrome上效果很好。但是,它不在任何其他浏览器上。有什么想法吗?

let i = 0;
setInterval(() => {
    document.body.style.backgroundImage = `url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='100%25'%3E%3Cdefs%3E%3ClinearGradient id='a' gradientUnits='userSpaceOnUse' x1='0' x2='0' y1='0' y2='100%25' gradientTransform='rotate(${i},814,458)'%3E%3Cstop offset='0' stop-color='%230f63ff'/%3E%3Cstop offset='1' stop-color='%23d90fff'/%3E%3C/linearGradient%3E%3Cpattern patternUnits='userSpaceOnUse' id='b' width='504' height='420' x='0' y='0' viewBox='0 0 1080 900'%3E%3Cg fill-opacity='0.15'%3E%3Cpolygon fill='%23444' points='90 150 0 300 180 300'/%3E%3Cpolygon points='90 150 180 0 0 0'/%3E%3Cpolygon fill='%23AAA' points='270 150 360 0 180 0'/%3E%3Cpolygon fill='%23DDD' points='450 150 360 300 540 300'/%3E%3Cpolygon fill='%23999' points='450 150 540 0 360 0'/%3E%3Cpolygon points='630 150 540 300 720 300'/%3E%3Cpolygon fill='%23DDD' points='630 150 720 0 540 0'/%3E%3Cpolygon fill='%23444' points='810 150 720 300 900 300'/%3E%3Cpolygon fill='%23FFF' points='810 150 900 0 720 0'/%3E%3Cpolygon fill='%23DDD' points='990 150 900 300 1080 300'/%3E%3Cpolygon fill='%23444' points='990 150 1080 0 900 0'/%3E%3Cpolygon fill='%23DDD' points='90 450 0 600 180 600'/%3E%3Cpolygon points='90 450 180 300 0 300'/%3E%3Cpolygon fill='%23666' points='270 450 180 600 360 600'/%3E%3Cpolygon fill='%23AAA' points='270 450 360 300 180 300'/%3E%3Cpolygon fill='%23DDD' points='450 450 360 600 540 600'/%3E%3Cpolygon fill='%23999' points='450 450 540 300 360 300'/%3E%3Cpolygon fill='%23999' points='630 450 540 600 720 600'/%3E%3Cpolygon fill='%23FFF' points='630 450 720 300 540 300'/%3E%3Cpolygon points='810 450 720 600 900 600'/%3E%3Cpolygon fill='%23DDD' points='810 450 900 300 720 300'/%3E%3Cpolygon fill='%23AAA' points='990 450 900 600 1080 600'/%3E%3Cpolygon fill='%23444' points='990 450 1080 300 900 300'/%3E%3Cpolygon fill='%23222' points='90 750 0 900 180 900'/%3E%3Cpolygon points='270 750 180 900 360 900'/%3E%3Cpolygon fill='%23DDD' points='270 750 360 600 180 600'/%3E%3Cpolygon points='450 750 540 600 360 600'/%3E%3Cpolygon points='630 750 540 900 720 900'/%3E%3Cpolygon fill='%23444' points='630 750 720 600 540 600'/%3E%3Cpolygon fill='%23AAA' points='810 750 720 900 900 900'/%3E%3Cpolygon fill='%23666' points='810 750 900 600 720 600'/%3E%3Cpolygon fill='%23999' points='990 750 900 900 1080 900'/%3E%3Cpolygon fill='%23999' points='180 0 90 150 270 150'/%3E%3Cpolygon fill='%23444' points='360 0 270 150 450 150'/%3E%3Cpolygon fill='%23FFF' points='540 0 450 150 630 150'/%3E%3Cpolygon points='900 0 810 150 990 150'/%3E%3Cpolygon fill='%23222' points='0 300 -90 450 90 450'/%3E%3Cpolygon fill='%23FFF' points='0 300 90 150 -90 150'/%3E%3Cpolygon fill='%23FFF' points='180 300 90 450 270 450'/%3E%3Cpolygon fill='%23666' points='180 300 270 150 90 150'/%3E%3Cpolygon fill='%23222' points='360 300 270 450 450 450'/%3E%3Cpolygon fill='%23FFF' points='360 300 450 150 270 150'/%3E%3Cpolygon fill='%23444' points='540 300 450 450 630 450'/%3E%3Cpolygon fill='%23222' points='540 300 630 150 450 150'/%3E%3Cpolygon fill='%23AAA' points='720 300 630 450 810 450'/%3E%3Cpolygon fill='%23666' points='720 300 810 150 630 150'/%3E%3Cpolygon fill='%23FFF' points='900 300 810 450 990 450'/%3E%3Cpolygon fill='%23999' points='900 300 990 150 810 150'/%3E%3Cpolygon points='0 600 -90 750 90 750'/%3E%3Cpolygon fill='%23666' points='0 600 90 450 -90 450'/%3E%3Cpolygon fill='%23AAA' points='180 600 90 750 270 750'/%3E%3Cpolygon fill='%23444' points='180 600 270 450 90 450'/%3E%3Cpolygon fill='%23444' points='360 600 270 750 450 750'/%3E%3Cpolygon fill='%23999' points='360 600 450 450 270 450'/%3E%3Cpolygon fill='%23666' points='540 600 630 450 450 450'/%3E%3Cpolygon fill='%23222' points='720 600 630 750 810 750'/%3E%3Cpolygon fill='%23FFF' points='900 600 810 750 990 750'/%3E%3Cpolygon fill='%23222' points='900 600 990 450 810 450'/%3E%3Cpolygon fill='%23DDD' points='0 900 90 750 -90 750'/%3E%3Cpolygon fill='%23444' points='180 900 270 750 90 750'/%3E%3Cpolygon fill='%23FFF' points='360 900 450 750 270 750'/%3E%3Cpolygon fill='%23AAA' points='540 900 630 750 450 750'/%3E%3Cpolygon fill='%23FFF' points='720 900 810 750 630 750'/%3E%3Cpolygon fill='%23222' points='900 900 990 750 810 750'/%3E%3Cpolygon fill='%23222' points='1080 300 990 450 1170 450'/%3E%3Cpolygon fill='%23FFF' points='1080 300 1170 150 990 150'/%3E%3Cpolygon points='1080 600 990 750 1170 750'/%3E%3Cpolygon fill='%23666' points='1080 600 1170 450 990 450'/%3E%3Cpolygon fill='%23DDD' points='1080 900 1170 750 990 750'/%3E%3C/g%3E%3C/pattern%3E%3C/defs%3E%3Crect x='0' y='0' fill='url(%23a)' width='100%25' height='100%25'/%3E%3Crect x='0' y='0' fill='url(%23b)' width='100%25' height='100%25'/%3E%3C/svg%3E")`

    if(i === 360){
        i = 0;
    } else {
        i++;
    }

}, 30);

1 个答案:

答案 0 :(得分:1)

从序列化的url数据重新呈现完整的图像仅花费太长时间。如果您内联编写SVG并仅为gradientTransform属性设置动画,则可以做得更好。下面的堆栈片段将<svg>元素呈现为HTML页面的<body>元素的直接子元素。

虽然有两种方式可以声明性地编写动画,但是它们都有兼容性问题:

  • 带有<animateTransform>元素的SMIL动画不适用于Edge / IE
  • CSS动画需要实现gradientTransform as a presentation attribute,这是SVG 2中的新功能,尚未在所有浏览器中实现(我没有数据,但是我看到它在Firefox中不起作用)

因此,脚本化变体实际上是您可以做的最好的事情;但是您应该使用window.requestAnimationFrame()方法来确保动画的运行与浏览器一样流畅。

let start = null;
const gradient = document.querySelector('#a');
function step(timestamp) {
    if (!start) start = timestamp;
    const degree = (timestamp - start) / 30 % 360;
    gradient.setAttribute('gradientTransform', `rotate(${degree},814,458)`);
    window.requestAnimationFrame(step);
}

window.requestAnimationFrame(step);
body { height: 100vh; margin: 0; }
<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%">
  <defs>
    <linearGradient id="a" gradientUnits="userSpaceOnUse" x1="0" x2="0" y1="0" y2="100%" gradientTransform="rotate(0,814,458)">
      <stop offset="0" stop-color="#0f63ff"/>
      <stop offset="1" stop-color="#d90fff"/>
    </linearGradient>
    <pattern patternUnits="userSpaceOnUse" id="b" width="504" height="420" x="0" y="0" viewBox="0 0 1080 900">
      <g fill-opacity="0.15">
        <polygon fill="#444" points="90 150 0 300 180 300"/>
        <polygon points="90 150 180 0 0 0"/>
        <polygon fill="#AAA" points="270 150 360 0 180 0"/>
        <polygon fill="#DDD" points="450 150 360 300 540 300"/>
        <polygon fill="#999" points="450 150 540 0 360 0"/>
        <polygon points="630 150 540 300 720 300"/>
        <polygon fill="#DDD" points="630 150 720 0 540 0"/>
        <polygon fill="#444" points="810 150 720 300 900 300"/>
        <polygon fill="#FFF" points="810 150 900 0 720 0"/>
        <polygon fill="#DDD" points="990 150 900 300 1080 300"/>
        <polygon fill="#444" points="990 150 1080 0 900 0"/>
        <polygon fill="#DDD" points="90 450 0 600 180 600"/>
        <polygon points="90 450 180 300 0 300"/>
        <polygon fill="#666" points="270 450 180 600 360 600"/>
        <polygon fill="#AAA" points="270 450 360 300 180 300"/>
        <polygon fill="#DDD" points="450 450 360 600 540 600"/>
        <polygon fill="#999" points="450 450 540 300 360 300"/>
        <polygon fill="#999" points="630 450 540 600 720 600"/>
        <polygon fill="#FFF" points="630 450 720 300 540 300"/>
        <polygon points="810 450 720 600 900 600"/>
        <polygon fill="#DDD" points="810 450 900 300 720 300"/>
        <polygon fill="#AAA" points="990 450 900 600 1080 600"/>
        <polygon fill="#444" points="990 450 1080 300 900 300"/>
        <polygon fill="#222" points="90 750 0 900 180 900"/>
        <polygon points="270 750 180 900 360 900"/>
        <polygon fill="#DDD" points="270 750 360 600 180 600"/>
        <polygon points="450 750 540 600 360 600"/>
        <polygon points="630 750 540 900 720 900"/>
        <polygon fill="#444" points="630 750 720 600 540 600"/>
        <polygon fill="#AAA" points="810 750 720 900 900 900"/>
        <polygon fill="#666" points="810 750 900 600 720 600"/>
        <polygon fill="#999" points="990 750 900 900 1080 900"/>
        <polygon fill="#999" points="180 0 90 150 270 150"/>
        <polygon fill="#444" points="360 0 270 150 450 150"/>
        <polygon fill="#FFF" points="540 0 450 150 630 150"/>
        <polygon points="900 0 810 150 990 150"/>
        <polygon fill="#222" points="0 300 -90 450 90 450"/>
        <polygon fill="#FFF" points="0 300 90 150 -90 150"/>
        <polygon fill="#FFF" points="180 300 90 450 270 450"/>
        <polygon fill="#666" points="180 300 270 150 90 150"/>
        <polygon fill="#222" points="360 300 270 450 450 450"/>
        <polygon fill="#FFF" points="360 300 450 150 270 150"/>
        <polygon fill="#444" points="540 300 450 450 630 450"/>
        <polygon fill="#222" points="540 300 630 150 450 150"/>
        <polygon fill="#AAA" points="720 300 630 450 810 450"/>
        <polygon fill="#666" points="720 300 810 150 630 150"/>
        <polygon fill="#FFF" points="900 300 810 450 990 450"/>
        <polygon fill="#999" points="900 300 990 150 810 150"/>
        <polygon points="0 600 -90 750 90 750"/>
        <polygon fill="#666" points="0 600 90 450 -90 450"/>
        <polygon fill="#AAA" points="180 600 90 750 270 750"/>
        <polygon fill="#444" points="180 600 270 450 90 450"/>
        <polygon fill="#444" points="360 600 270 750 450 750"/>
        <polygon fill="#999" points="360 600 450 450 270 450"/>
        <polygon fill="#666" points="540 600 630 450 450 450"/>
        <polygon fill="#222" points="720 600 630 750 810 750"/>
        <polygon fill="#FFF" points="900 600 810 750 990 750"/>
        <polygon fill="#222" points="900 600 990 450 810 450"/>
        <polygon fill="#DDD" points="0 900 90 750 -90 750"/>
        <polygon fill="#444" points="180 900 270 750 90 750"/>
        <polygon fill="#FFF" points="360 900 450 750 270 750"/>
        <polygon fill="#AAA" points="540 900 630 750 450 750"/>
        <polygon fill="#FFF" points="720 900 810 750 630 750"/>
        <polygon fill="#222" points="900 900 990 750 810 750"/>
        <polygon fill="#222" points="1080 300 990 450 1170 450"/>
        <polygon fill="#FFF" points="1080 300 1170 150 990 150"/>
        <polygon points="1080 600 990 750 1170 750"/>
        <polygon fill="#666" points="1080 600 1170 450 990 450"/>
        <polygon fill="#DDD" points="1080 900 1170 750 990 750"/>
      </g>
    </pattern>
  </defs>
  <rect x="0" y="0" fill="url(#a)" width="100%" height="100%"/>
  <rect x="0" y="0" fill="url(#b)" width="100%" height="100%"/>
</svg>