D3.js v5分组柱状图:实现x.domain标签与数据分离
Grouped Bar Chart with D3.js v5 (Separate X-Domain from Data)
Got it, let's build this grouped bar chart step by step, making sure we keep the x-axis domain labels fully independent from the raw data structure. Here's a complete, working implementation tailored to your data:
1. Basic HTML Setup
First, add an SVG container to your page where the chart will render:
<svg id="groupedBarChart" width="800" height="500"></svg>
2. D3.js Implementation
Here's the JavaScript code, with detailed comments explaining each key part:
// Your provided raw data var groupeddata = [ { Title: "Dummy Data", ID: "46", RFU: 20291, Name: "Name1", barcolor: "#ff7f00"}, { Title: "Dummy Data", ID: "50", RFU: 15000, Name: "Name2", barcolor: "#ff7f00"}, { Title: "Dummy Data", ID: "40", RFU: 14000, Name: "Name3", barcolor: "#ff7f00"}, { Title: "Dummy Data2", ID: "46", RFU: 21000, Name: "Name1", barcolor: "#8B008B"}, { Title: "Dummy Data2", ID: "50", RFU: 18095, Name: "Name2", barcolor: "#8B008B"}, { Title: "Dummy Data2", ID: "40", RFU: 16000, Name: "Name3", barcolor: "#8B008B"} ]; // Set up SVG dimensions and margins const svg = d3.select("#groupedBarChart"); const margin = { top: 30, right: 30, bottom: 60, left: 60 }; const width = +svg.attr("width") - margin.left - margin.right; const height = +svg.attr("height") - margin.top - margin.bottom; const g = svg.append("g").attr("transform", `translate(${margin.left},${margin.top})`); // --- Core part: Separate x-axis domain labels from data --- // Extract unique category names (these become our x-axis labels) const xLabels = [...new Set(groupeddata.map(d => d.Name))]; // Extract unique group titles (these define our bar series) const groups = [...new Set(groupeddata.map(d => d.Title))]; const groupCount = groups.length; // Create scales // Main x-scale for category labels (Name1, Name2, Name3) const x0 = d3.scaleBand() .domain(xLabels) .range([0, width]) .padding(0.2); // Secondary x-scale for positioning bars within each category const x1 = d3.scaleBand() .domain(groups) .range([0, x0.bandwidth()]) .padding(0.1); // Y-scale for RFU values const y = d3.scaleLinear() .domain([0, d3.max(groupeddata, d => d.RFU)]) .nice() // Rounds the domain to a clean number .range([height, 0]); // Add axes g.append("g") .attr("transform", `translate(0,${height})`) .call(d3.axisBottom(x0)) .selectAll("text") .attr("y", 10) .attr("x", -5) .attr("text-anchor", "end") .attr("transform", "rotate(-45)"); // Rotate labels to avoid overlap g.append("g") .call(d3.axisLeft(y)) .append("text") .attr("transform", "rotate(-90)") .attr("y", -50) .attr("fill", "#000") .attr("text-anchor", "middle") .text("RFU Value"); // --- Draw the grouped bars --- // First, group data by category Name for easier iteration const dataByCategory = d3.group(groupeddata, d => d.Name); // Loop through each category and draw its bars dataByCategory.forEach((categoryData, categoryName) => { const baseX = x0(categoryName); g.selectAll(`.bar-${categoryName}`) .data(categoryData) .enter() .append("rect") .attr("class", `bar-${categoryName}`) .attr("x", d => baseX + x1(d.Title)) .attr("y", d => y(d.RFU)) .attr("width", x1.bandwidth()) .attr("height", d => height - y(d.RFU)) .attr("fill", d => d.barcolor); }); // Add a legend for clarity const legend = g.append("g") .attr("transform", `translate(${width - 150}, 0)`); groups.forEach((group, index) => { const legendRow = legend.append("g") .attr("transform", `translate(0, ${index * 25})`); legendRow.append("rect") .attr("width", 15) .attr("height", 15) .attr("fill", groupeddata.find(d => d.Title === group).barcolor); legendRow.append("text") .attr("x", 20) .attr("y", 12) .style("font-size", "12px") .text(group); });
Key Details on Separating X-Domain from Data
- We pull
xLabelsdirectly from theNamefield usingnew Set()to get unique values—this ensures the x-axis domain is completely decoupled from other data fields likeTitleorID. - Two x-scales work together:
x0handles the main category positioning, whilex1slots each group's bar into the category's space. - Using
d3.group()(available in D3 v5+) simplifies mapping raw data to the grouped bar structure, making updates to data or labels straightforward.
This implementation will render a clean, functional grouped bar chart where you can modify the x-axis labels or data independently without breaking the chart's structure.
内容的提问来源于stack exchange,提问作者Coola
相关产品推荐
相关产品推荐

