对于此d3示例,如何防止/最小化回流焊?

问题描述 投票:1回答:1

我具有以下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来触发的,而是通过在这些元素上设置classid属性来触发的。果然,如果我删除第4行和第5行,回流速度的降低将完全消失。设置其他属性(例如data-something)不会导致速度降低/重排。

问题是,如上所述,我之后无法再分别操纵这些路径。我的问题是:

  • 为什么将classid添加到父级设置为display: none的元素会触发重排?
  • 我该如何解决?如何在不降低速度的情况下设置这些属性?
javascript d3.js svg
1个回答
0
投票

阅读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更改会导致重排,但是我不再为此受阻。

© www.soinside.com 2019 - 2024. All rights reserved.