我有以下d3逻辑可用于渲染单个对象:
svg.selectAll("path")
.data(hugePathDataset)
.enter().append("path")
.attr("class", (d) => d.properties.cls )
.attr("id", (d) => d.properties.name )
.each(... canvas render logic ...)
出于性能原因,上面的
svg
元素设置为display: none
,真正的渲染通过d3
的投影逻辑在画布上进行。但是,仍然需要svg元素,以便以后对画布进行更新(例如,分别更改每个路径的颜色)。我的数据集包含60,000多个路径,以上代码需要大约30秒才能运行。在Chrome的探查器中对其进行测试,我注意到90%的时间都花在了回流焊上。这对我来说毫无意义,因为画布不会重排,并且带有
display: none
的SVG不应重排DOM。当我继续研究时,我意识到重排不是通过将元素附加到不可见的SVG来触发的,而是通过在这些元素上设置class
和id
属性来触发的。果然,如果我删除第4行和第5行,回流速度的降低将完全消失。设置其他属性(即data-something
)不会导致速度降低/重排。问题是如上所述,我随后无法再分别操纵这些路径。我的问题是:
为什么将
class
或id
添加到父级设置为display: none
的元素会触发重排?我该如何解决?如何在不降低速度的情况下设置这些属性?
最佳答案
阅读D3文档后,我意识到selection.append("path")
等同于selection.append(() => document.createElement("path"))
。由于document.createElement
尚未将元素附加到DOM,因此可以安全地在其上设置属性而不进行重排。我以不同的方式重写了以上逻辑,问题消失了:
svg.selectAll("path")
.data(hugePathDataset)
.enter().append((d) => {
let element = document.createElement("path");
element.id = d.properties.name;
element.className = d.properties.cls;
return element;
})
.each(... canvas render logic ...)
我仍然不明白为什么不可见元素上的类/ id更改会导致重排,但是,我不再为此受阻。
关于javascript - 如何防止/最小化此d3示例的重排?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/58137979/