SVG 属性和样式之间是不是存在性能差异?

Posted

技术标签:

【中文标题】SVG 属性和样式之间是不是存在性能差异?【英文标题】:Is there a performance difference between SVG attributes and styles?SVG 属性和样式之间是否存在性能差异? 【发布时间】:2014-05-17 23:59:05 【问题描述】:

我正在处理包含大量小元素的大型 SVG 粒子动画。有时多达 1000 个。当我为这么多元素设置动画时,浏览器似乎很困难,所以我正在寻找优化代码以获得更好、更流畅的性能(尤其是 Firefix)的方法。

我的主要问题是,例如,将元素的 stroke 属性设置为属性或样式之间是否有任何区别:

<circle r="0.15" cx="84" cy="782" stroke- stroke="transparent" style="fill: #ffffff;"></circle>

<circle r="0.15" cx="84" cy="782" stroke- stroke="transparent" style="stroke:transparent; stroke-width:6; fill: #ffffff;"></circle>

我正在使用 D3.js 添加一堆这样的东西并让它们四处移动......在 Chrome 变得笨拙之前,1000 似乎大致是极限。 Firefox 更糟糕。

如果您有任何其他性能建议,也欢迎提出。

更新 按要求:

这是我创建节点的方式:

var makeNode = function(coeficient, x, y) 
    coeficient = coeficient || 1;
    return 
        radius: (Math.random() * coeficient ).toFixed(2), 
        cx: function()  return x || Math.round(Math.random()*width) , 
        cy: function()  return y || Math.round(Math.random()*height) 
    
;

var nodes1 = d3.range(300).map( function() return makeNode(1.9);  );
var nodes2 = d3.range(700).map( function() return makeNode(.6);  );
// var nodes2 = [];

var svg = d3.select('#sky_svg');
var group1 = svg.append('g').attr("class", "group1");
var group2 = svg.append('g').attr("class", "group2");

var addNodes = function(group, nodes) 
    for (var i=0; i<nodes.length; i++)
        var node = nodes[i];
        var circle = group.append('circle');
        circle
            .attr("r", node.radius )
            .attr("cx", node.cx )
            .attr("cy", node.cy )
            .attr("stroke-width", 8 )
            .attr("stroke", "transparent")
            .style("fill", "#FFFFFF");
    


addNodes( group1, nodes1 );
addNodes( group2, nodes2 );

这就是我制作动画的方式:

function orbit( target, ease, duration ) 

  /* Other easing options here: https://github.com/mbostock/d3/wiki/Transitions#wiki-d3_ease */
ease = ease || 'linear';
duration = duration || 40000;

  target
    .transition()
    .duration( duration )
    .ease( ease )
    .attrTween("transform", rotTween)
    .each('end', function() orbit( group1, false );  );

  function rotTween() 
      var i = d3.interpolate(0, 360);
      return function(t) 
          return "rotate(" + i(t) + ","+width/2+","+height/2+")";
      ;
  



orbit( group1, 'sin-in', orbitSpeed );
orbit( group2, 'sin-in', orbitSpeed*2.5 );

我并不是特别喜欢这个实现。我最初的设计使用了强制布局,但是 Firefox 很难真的 甚至很难加载它,然后它运行得非常糟糕,所以我重构了代码以使用简单的旋转(这在 FF 中几乎可以顺利运行)。

【问题讨论】:

这几乎可以保证是特定于实现的,因此对于所有性能问题,您必须对其进行衡量。 这看起来很像 html。您如何使用 JS/D3 实际创建这些圆圈? @user13500 D3 可以更改元素属性或更改内联样式,除了功能几乎相同。 @SDP 它可能在强制布局刻度函数中内联样式会稍微更有效,因为它们会自动覆盖所有样式表样式,因此浏览器不会必须扫描级联以确定活动风格,但正如@MattBall 所说,你真的必须测试看看是否有区别。但是,如果使用转换,它可以被反转,因为transition.style() 使用getComputedStyle 访问初始值,这将比getAttribute 慢(尽管这只会延迟过渡,而不是动画)。 @AmeliaBR:是的,但我真的很想看到一些代码来更好地评估可能的罪魁祸首。至少更多的上下文。我喜欢 Q 是重点,但绝不会少...... Eramfh!我现在可能更适合睡觉。, 【参考方案1】:

圈子有 baseVal 代表 cx,cy,r。有人建议通过baseVal 访问这些属性。使用setAttributeattr(在d3 中)更有效。 例如

myCircle.cx.baseVal.value=myCx
myCircle.cy.baseVal.value=myCy
myCircle.r.baseVal.value=myR

【讨论】:

以上是关于SVG 属性和样式之间是不是存在性能差异?的主要内容,如果未能解决你的问题,请参考以下文章

元素属性的jQuery动画不是样式

这些在 React 中使用三元运算符有条件地应用内联样式的方法在性能上是不是有任何差异?

视图和存储过程之间是不是存在性能差异

视图和内联表函数之间是不是存在性能差异?

for 循环和 for-each 循环之间是不是存在性能差异?

C# 中的 ++i 和 i++ 之间是不是存在性能差异?