如何使用d3.create创建并附加分离元素?附常规实现示例
使用D3的d3.create创建并附加分离元素
嘿,我来帮你理清楚怎么用d3.create创建和附加分离元素!
首先,先搞懂d3.create的核心作用:它能创建一个脱离当前DOM树的元素(也就是你说的"分离元素"),你可以先在这个内存中的元素上完成所有配置(绑定数据、设置样式、添加子元素等等),最后再把它挂载到页面的DOM结构里。这种方式的好处是减少DOM重排重绘,提升性能,同时让代码更模块化。
对比你的原始代码,改造后的示例
你的原始代码是直接在页面已有的<svg>里创建元素,现在我们用d3.create来重构:
<!doctype html> <html lang="en"> <head> <script src="https://d3js.org/d3.v5.min.js"></script> </head> <body> <svg></svg> <script> const svg = d3.select('svg'); // 1. 创建一个分离的<g>元素,此时它还不在页面DOM中 const detachedGroup = d3.create('g'); // 2. 在这个分离的组上完成所有元素配置(顺便修正了一个小细节) detachedGroup.append('g') .selectAll('rect') // 这里原来写的是selectAll('g'),应该匹配我们要创建的rect元素 .data([5, 10, 20, 40]) .enter() .append('rect') .attr('fill', 'green') .attr('x', d => d) .attr('y', d => d) .attr('height', d => d) .attr('width', d => d); // 3. 把分离的组附加到页面的svg中 // 用.node()获取底层DOM节点,通过append的函数参数传入 svg.append(() => detachedGroup.node()); </script> </body> </html>
关键步骤拆解
创建分离元素:
调用d3.create('元素选择器'),比如d3.create('g')就创建了一个<g>元素,这个元素一开始只存在于内存中,不会出现在页面上。它返回的是一个D3选择集,所以你可以像操作其他D3选择集一样调用append、attr等方法。配置分离元素:
你可以在这个分离的元素上做任何你需要的操作——绑定数据、添加子元素、设置样式、添加事件监听等等,所有操作都是在内存中完成的,不会触发页面的重排。附加到DOM树:
完成配置后,用.node()方法获取分离元素的原生DOM节点,然后通过两种方式挂载:- D3方式:
目标选择集.append(() => 分离元素.node()) - 原生DOM方式:
document.querySelector('svg').appendChild(分离元素.node())
- D3方式:
更灵活的场景:创建分离的SVG元素
你也可以用d3.create直接创建整个分离的<svg>,配置好后再加到页面里,比如:
// 创建分离的svg,设置宽高 const detachedSvg = d3.create('svg') .attr('width', 200) .attr('height', 200); // 在分离的svg里添加元素 detachedSvg.append('circle') .attr('cx', 100) .attr('cy', 100) .attr('r', 50) .attr('fill', 'steelblue'); // 把svg挂载到body里 document.body.appendChild(detachedSvg.node());
为什么用这种方式?
- 性能优化:批量操作内存中的元素,最后一次性挂载,减少DOM重排重绘的次数,页面更流畅。
- 代码模块化:可以把创建某个组件的逻辑封装成函数,返回分离的元素,然后在需要的地方挂载,比如:
function createGreenRects(data) { const group = d3.create('g'); group.append('g') .selectAll('rect') .data(data) .enter() .append('rect') .attr('fill', 'green') .attr('x', d => d) .attr('y', d => d) .attr('height', d => d) .attr('width', d => d); return group; } // 调用函数并挂载 const svg = d3.select('svg'); svg.append(() => createGreenRects([5,10,20,40]).node());
内容的提问来源于stack exchange,提问作者Nibor
相关产品推荐
相关产品推荐

