D3.js图表问题:仅一个圆形可见其余超出SVG高度
Hey there! Let's figure out why only one of your circles is showing up—this is a super common gotcha with D3.js and SVG coordinate systems.
The Root Cause
Chances are, you're not using a scale to map your score data values to the actual height of your SVG container. Here's the breakdown:
- Your internal SVG height (after margins) is
500 - 40 - 40 = 420pixels. - Your
scorevalues range from 100 all the way up to 2000. If you're settingcydirectly tod.score, any score over 420 will place the circle below the visible area of your SVG. Only the smallest score (100) would land within the 0-420 pixel range, hence only one circle showing up. - On top of that, SVG's y-axis starts at the top (y=0 is the top edge), so even if you did fit values, your largest scores would be at the bottom unless you reverse the scale.
Fix Steps
Let's walk through the corrections you need to make:
Add a Linear Scale for the Y-Axis
Create a scale that maps yourscoredata domain to the pixel range of your SVG. We'll reverse the range so larger scores appear higher up (more intuitive for most charts):// Calculate the min/max of your score data const scoreExtent = d3.extent(data, d => d.score); // Create the y-scale const yScale = d3.scaleLinear() .domain(scoreExtent) // Data range: [100, 2000] .range([height, 0]); // SVG pixel range: bottom (height) to top (0)Use the Scale to Position Circles
When setting thecyattribute for your circles, use the scale instead of the rawscorevalue:// First, make sure your SVG is set up with margins correctly const svg = d3.select("body") .append("svg") .attr("width", width + margin.left + margin.right) .attr("height", height + margin.top + margin.bottom) .append("g") .attr("transform", `translate(${margin.left}, ${margin.top})`); // Now draw the circles svg.selectAll("circle") .data(data) .enter() .append("circle") .attr("cx", d => { // Add an x-scale for age to spread circles horizontally const xScale = d3.scaleLinear() .domain(d3.extent(data, d => d.age)) .range([0, width]); return xScale(d.age); }) .attr("cy", d => yScale(d.score)) // Use the y-scale here! .attr("r", 8) .attr("fill", "#2c3e50");Verify SVG Container Size
Double-check that your main SVG element includes the margin values in its total width/height. If you forget this, even scaled elements might get clipped at the edges.
Why This Works
- The scale compresses your large
scorevalues (like 2000) down to fit within the 0-420 pixel height of your SVG's internal group. - Reversing the
range([height, 0])ensures that higher scores are positioned near the top of the SVG, which matches how we typically read charts.
Give this a try, and all your circles should show up properly within the SVG bounds!
内容的提问来源于stack exchange,提问作者user1310969

