这种在IE9中旋转SVG的方法是否会导致性能下降?

时间:2018-01-04 13:24:32

标签: javascript animation svg

我有一个任务是在IE9中进行SVG旋转。

我发现FakeSmile库让它旋转,但是在整个DOM准备就绪后,这不是我想要的行为。我尝试使用JavaScript手动完成并以此代码结束:

//init an array with values from 0 to 360 for degrees 
var degrees = [];
for(var i = 0; i <= 360; i++) {
    degress.push(i);
}
// function to rotate it, after it's fetched from the DOM
var rotate = function() {
    var deg = degrees.shift();
    element.style.msTransform = "rotate(" + deg + "deg)";
    degrees.push(deg);         
}
setInterval(rotate, 7);

虽然它正在运行,但我担心是否会出现任何性能损失。如果有更好的解决方案。欢迎任何建议。

2 个答案:

答案 0 :(得分:1)

创建者功能和有组织的对象将是一个良好的开端。请记住,如果可以避免,则不应污染全局命名空间。

同时退出请求和动画。每7毫秒的请求是在60fps屏幕上每帧两个请求(最常见),并且不需要计算并丢弃用户从未看到的帧。

在我的示例中,我使用requestAnimationFrame因为它将与屏幕刷新同步。在每次请求时,我都会检查手柄是否已经绘制了一个框架,如果不是,我会安排一个框架图。

请注意,您仍然可以每7毫秒设置一次JavaScript变量。只是DOM的速度变慢了。

编辑1 - IE9中没有requestAnimationFrame

我对requestAnimationFrame的错误,但是反弹仍然是一个好主意。通过去抖动,有几个因素可以请求更改,它仍然只会在相关时呈现。

我已将requestAnimationFrame替换为setTimeout(.... 1000/60),接近60 fps动画。

function createRotator(element) {
  var rotator;
  rotator = {
    degrees: 0,
    element: element,
    eventHandle: false,
    rotate: function rotate() {
      rotator.degrees = (rotator.degrees + 1) % 360;
      if (rotator.eventHandle === false)
        rotator.eventHandle = setTimeout(function() {
          rotator.element.style.transform = "rotate(" + rotator.degrees + "deg)";
          rotator.element.style.msTransform = "rotate(" + rotator.degrees + "deg)";
          rotator.eventHandle = false;
        }, 1000 / 60);
    }
  };
  return rotator;
}
//TEST
var nodes = 0;
var handle;
handle = setInterval(function() {
  nodes++;
  if (nodes > 10) {
    clearInterval(handle);
  }
  var testNode = document.body.appendChild(document.createElement("p"));
  testNode.innerHTML = "Hello dear World!";
  testNode.style.width = "115px";
  testNode.style.cssFloat = "left";
  testNode.style.marginTop = "100px";
  var rotator = createRotator(testNode);
  setInterval(rotator.rotate, 3);
}, 1000 / 4);

答案 1 :(得分:0)

是的,使用IE9,你在CSS动画上运气不佳。我唯一的建议是内存优化

//init a variable to store the current angle
let angle = 0;

// function to rotate it
function rotate() {
    angle = (++angle)%360;
    element.style.msTransform = "rotate(" + angle+ "deg)";      
}
setInterval(rotate, 7);

此设计更改还允许您在不改变间隔长度的情况下即时更改旋转速度。您要更改的是++angleangle + w,其中w是角速度。

不幸的是,您不能使用requestAnimationFrame而不是间隔。那好吧。它不是世界末日。

编辑: 令我烦恼的是,该功能在很大程度上依赖于全局变量。所以,这是一个稍微好一点的#34;虽然更重,但这样做的方式。

/** Takes in an element, an angular velocity, and an interval, and makes the element spin in IE9
PARAMS:
    element  : Element - The element we are spinning
    da       : Number  - The angular velocity in degrees per interval
    interval : Number  - The number of milliseconds per interval
RETURNS:
    Number - The ID of the interval that is created
**/
function makeRotate(element, da, interval){
    // Variable to store angle
    let a = 0;

    // If da isn't provided, make it 1
    da = da || 1;

    // If interval isn't provided, make it 7
    interval = interval || 7;

    // Get the ID and make the interval
    let id = window.setInterval(() => {

        // Increment the angle by the angular velocity, but wrap around 360
        a = (a + da)%360;

        // Apply the transform to the element
        element.style.msTransform = "rotate(" + a + "deg)";      
    }, interval);

    // Return the ID of the interval
    return id;
}
const intervalId = makeRotate(element, 1, 7);

另外,我确保返回间隔ID,因为能够取消那些吸盘总是很方便! window.clearInterval(intervalId);