平滑的SVG动画

时间:2017-07-19 03:04:33

标签: javascript jquery animation svg

我正在尝试使用给定参数rotateX和rotateY刷新动画:

$(document).ready(function() {
        var svg = document.getElementById("DC");
        var x = 10;
        var y = 0;
        for (j = 0; j<8 ; j++) {
            svg.setAttribute('style', 'transform: perspective(30em) rotateX(' + x + 'deg) rotateY(' + y + 'deg) scale(0.6, 0.6); perspective: 30em;');
            x = x  + 10;
        }
    });

但它没有用。如何顺利刷新动画?

以下是HTML代码:

<body><svg id="DC" version="1.0" viewBox="0 0 500 408" class="sim" x="0px" y="0px" width="100%" height="100%" style="transform: perspective(30em) rotateX(0deg) rotateY(0deg) scale(0.6, 0.6); perspective: 30em;"><style></body>

3 个答案:

答案 0 :(得分:2)

问题在于,每次执行动画时,都需要为浏览器提供绘制更改的机会。你不是那样做的。您的for循环只是不断更改style属性,并且永远不会将控制权返回给浏览器。它永远没有机会更新页面。

有几种方法可以解决这个问题。曾几何时,通常使用window.setTimeout()调用返回浏览器并让它调用您的代码以更新动画。现在,首选的方式是requestAnimationFrame()电话。

var svg = document.getElementById("DC");
var x = 10;
var y = 0;

function step(timestamp)
{
   svg.setAttribute('style', 'transform: perspective(30em) rotateX(' + x + 'deg) rotateY(' + y + 'deg) scale(0.6, 0.6); perspective: 30em;');
   x = x  + 10;
   window.requestAnimationFrame(step);
}

window.requestAnimationFrame(step);
svg {
  background-color: red;
}
<body>
<svg id="DC" version="1.0" viewBox="0 0 500 408" class="sim" x="0px" y="0px" width="100%" height="100%" style="transform: perspective(30em) rotateX(0deg) rotateY(0deg) scale(0.6, 0.6); perspective: 30em;"></svg>
</body>

此处动画的每个步骤都在step()函数中计算。然后,在您退回此功能之前,您必须再次致电requestAnimation(),要求其再次致电step()

最后的调用是从头开始动画。

答案 1 :(得分:1)

一个简单的解决方案是使用CSS过渡 这样您就可以轻松定义速度,甚至可以使用定时功能。

&#13;
&#13;
var svg = document.getElementById("DC");

function update(x)
{
   svg.setAttribute('style', 'transform: perspective(30em) rotateX('+x+'deg) rotateY(0deg) scale(0.6, 0.6); perspective: 30em;');
}
svg.parentNode.offsetWidth;
update(80);

num.onchange = e => update(num.value);
&#13;
svg {
  background-color: red;
  transition: transform 2s ease-out;
}
&#13;
<label>x rotation<input type="number" value="80" id="num"></label>
<svg id="DC" version="1.0" viewBox="0 0 500 408" class="sim" x="0px" y="0px" width="100%" height="100%" style="transform: perspective(30em) rotateX(0deg) rotateY(0deg) scale(0.6, 0.6); perspective: 30em;"></svg>
&#13;
&#13;
&#13;

如果您需要循环播放,可以收听transitionend事件:

&#13;
&#13;
var svg = document.getElementById("DC");
x = 0;
function loop()
{
  x += 180;
  svg.setAttribute('style', 'transform: perspective(30em) rotateX('+x+'deg) rotateY(0deg) scale(0.6, 0.6); perspective: 30em;');
}
svg.addEventListener('transitionend', loop);
svg.parentNode.offsetWidth;
loop();
&#13;
svg {
  background-color: red;
  transition: transform .5s linear;
}
&#13;
<svg id="DC" version="1.0" viewBox="0 0 500 408" class="sim" x="0px" y="0px" width="100%" height="100%" style="transform: perspective(30em) rotateX(0deg) rotateY(0deg) scale(0.6, 0.6); perspective: 30em;"></svg>
&#13;
&#13;
&#13;

答案 2 :(得分:0)

尝试一些建议:      1.使用绝对定位和静态维度隔离在DOM中转换的元素      2.设置css属性will-change: transform;

<body>
       <div class="viewport" style="position: relative; width: 500px; height: 408px;">
             <svg id="DC" version="1.0" viewBox="0 0 500 408" class="sim" width="500px" height="408px" style="transform: perspective(30em) rotateX(0deg) rotateY(0deg) scale(0.6, 0.6); transform-origin: 0px 0px 0px; will-change: transform;">
               </svg>
         </div>

     3.使用转换计时功能,例如jquery.animate而不是for循环,它指示浏览器立即渲染所有帧。我不确定jquery可以为复杂变换设置动画,但是D3确定可以。您也可以这样做以将动画放入动画队列,但仍然可以使用具有计时功能的库:

function animate(frames,x) {
    if(frames > 0) {
        svg.setAttribute('style', 'transform: perspective(30em) rotateX(' + x + 'deg) rotateY(' + y + 'deg) scale(0.6, 0.6); perspective: 30em;');

         requestAnimationFrame(function() { animate(--frames,x+= 10); });
    }
    return;
}