如何在同一页面中放置两个D3环形图
嘿,这个问题其实很适合用代码复用来解决——把环形图的绘制逻辑封装成一个可复用的函数,只需要传入不同的数据和容器,就能轻松生成多个结构一致的图表,完全避免重复代码。我给你整理了一个完整的示例,你可以参考下:
解决方案:封装可复用的环形图函数
核心思路是把环形图的通用绘制逻辑抽成一个独立函数,通过传入不同的容器选择器和数据集来生成不同的图表,位置可以通过CSS控制容器来实现。
1. 准备HTML结构
给两个环形图分别准备独立的容器,方便控制位置:
<div id="donut-chart-1" class="donut-container"></div> <div id="donut-chart-2" class="donut-container"></div>
用CSS设置容器的位置(比如并排显示,你可以根据需求调整):
.donut-container { width: 300px; height: 300px; float: left; margin: 0 20px; }
2. 封装D3.js环形图函数
这个函数接收两个关键参数:containerSelector(指定图表要渲染到哪个容器)和data(当前图表的数据集),其他样式、尺寸参数统一设置(满足你“除数据和位置外完全一致”的要求):
function createDonutChart(containerSelector, data) { // 通用配置(所有图表共享) const width = 300; const height = 300; const radius = Math.min(width, height) / 2; const color = d3.scaleOrdinal(d3.schemeCategory10); // 清除容器内已有内容(避免重复渲染) d3.select(containerSelector).selectAll("*").remove(); // 创建SVG,绑定到指定容器 const svg = d3.select(containerSelector) .append("svg") .attr("width", width) .attr("height", height) .append("g") .attr("transform", `translate(${width/2}, ${height/2})`); // 创建弧生成器 const arc = d3.arc() .innerRadius(radius * 0.6) // 内环半径,控制环形粗细 .outerRadius(radius); // 创建饼图布局 const pie = d3.pie() .value(d => d.value) .sort(null); // 绑定数据,绘制环形路径 const arcs = svg.selectAll("arc") .data(pie(data)) .enter() .append("g"); arcs.append("path") .attr("d", arc) .attr("fill", (d, i) => color(i)) .attr("stroke", "#fff") .attr("stroke-width", 2); // 添加中心文本(可选,根据你的需求调整或删除) svg.append("text") .attr("text-anchor", "middle") .attr("dy", "0.35em") .style("font-size", "18px") .text(() => { const total = d3.sum(data, d => d.value); return `总计: ${total}`; }); }
3. 调用函数生成两个环形图
准备不同的数据集,然后分别调用函数即可:
// 第一个图表的数据 const data1 = [ { label: "A", value: 30 }, { label: "B", value: 50 }, { label: "C", value: 20 } ]; // 第二个图表的数据 const data2 = [ { label: "X", value: 45 }, { label: "Y", value: 35 }, { label: "Z", value: 20 } ]; // 生成两个环形图 createDonutChart("#donut-chart-1", data1); createDonutChart("#donut-chart-2", data2);
为什么这样做?
- 避免代码重复:所有通用逻辑只写一次,修改样式、交互时只需要改函数,不用两个图表分别调整
- 位置灵活控制:通过CSS控制容器的位置(比如并排、上下排列、绝对定位等),完全满足你“位置不同”的需求
- 可扩展性强:如果之后需要加更多环形图,只需要再调用一次函数,传入新的容器和数据就行
如果你的现有代码里有自定义的样式或交互,只需要把对应的逻辑移到这个通用函数里,保持参数只传数据和容器就好~
内容的提问来源于stack exchange,提问作者user8893965
相关产品推荐
相关产品推荐

