在数据可视化领域,D3.js作为JavaScript库的行业标杆,其饼状图功能被广泛应用于网站数据分析呈现,本文将以实战方式演示如何为D3.js饼状图添加专业级交互图例,通过符合W3C标准的代码实现可视化组件间的动态联动。(注:本教程基于D3.js v7版本,代码可直接嵌入React/Vue等主流框架)
<div id="chart-container"> <svg id="pie-chart"></svg> <div id="legend"></div> </div> <script src="https://d3js.org/d3.v7.min.js"></script> <style> .legend-item:hover { cursor: pointer; opacity: 0.8; } .legend-text { font: 12px sans-serif; dominant-baseline: middle; } </style>
步骤解析:
色彩方案配置
const color = d3.scaleOrdinal() .domain(data.map(d => d.category)) .range(d3.schemeCategory10);
图例坐标算法
const legendSpacing = 24; const generateLegendPosition = (index) => `translate(0,${index * legendSpacing})`;
动态绑定数据
const legend = d3.select("#legend") .selectAll("g") .data(color.domain()) .join("g") .attr("transform", (d,i) => generateLegendPosition(i));
legend.append("rect") .attr("width", 18) .attr("height", 18) .attr("fill", d => color(d)); legend.append("text") .attr("class", "legend-text") .attr("x", 24) .attr("y", 9) .text(d => d);
// 图例点击事件 legend.on("click", function(event, category) { const isActive = d3.select(this).classed("inactive"); d3.select(this).classed("inactive", !isActive); // 联动饼图显隐 pieChart.selectAll("path") .filter(d => d.data.category === category) .transition() .duration(500) .attr("opacity", isActive ? 1 : 0.2); }); // 悬浮高亮 pieChart.selectAll("path") .on("mouseover", function() { d3.select(this).transition().attr("opacity", 0.8); }) .on("mouseout", function() { d3.select(this).transition().attr("opacity", 1); });
function resizeChart() { const containerWidth = document.getElementById('chart-container').offsetWidth; svg.attr("width", containerWidth * 0.7); d3.select("#legend") .style("left", `${containerWidth * 0.72}px`); } window.addEventListener("resize", resizeChart);
const dataset = [ {category: "电子产品", value: 215}, {category: "图书教材", value: 178}, {category: "家居用品", value: 142}, {category: "服装饰品", value: 108} ]; const width = 600, height = 400, radius = Math.min(width, height) / 2; const svg = d3.select("#pie-chart") .attr("width", width) .attr("height", height) .append("g") .attr("transform", `translate(${width/2},${height/2})`); const pie = d3.pie().value(d => d.value)(dataset); const arc = d3.arc().innerRadius(0).outerRadius(radius); svg.selectAll("path") .data(pie) .join("path") .attr("d", arc) .attr("fill", d => color(d.data.category));
role="img" aria-label="统计图表"
提升无障碍访问requestAnimationFrame
优化交互动画性能d3.format(",.0f")
添加数据格式化显示引用说明: