在使用数据数组时,D3图表无法显示柱状图中的柱子,遇到了麻烦

前端开发 2026-07-10

我有一组数据,包含年份和百分比,正在尝试用d3绘制柱状图。输入一组我确信能工作的数字时,可以画出一个柱状条,但在使用x 轴、y轴以及一个数据数组时,屏幕上却没有任何显示。我没有收到任何错误信息。

我对d3还很新,学习曲线也挺陡的,所以如果有人能解释这里的问题,我将不胜感激。

<!DOCTYPE html>
<div id="container"></div>
<script src="https://cdn.jsdelivr.net/npm/d3@7"></script>
<script type="module">

// Declare the chart dimensions and margins.
const width = 1140;
const height = 500;
const marginTop = 20;
const marginRight = 20;
const marginBottom = 50;
const marginLeft = 70;

// Declare the x (horizontal position) scale.

const x = d3.scaleUtc()
            .domain([new Date("2017-01-01"), new Date("2024-01-01")])
            .range([marginLeft, width - marginRight]); //same as .range([70,1120])

// Declare the y (vertical position) scale.

const y = d3.scaleLinear()
            .domain([0, 1.00])
            .range([height - marginBottom, marginTop]); //same as .range([350, 20])

// Create the SVG container.
const svg = d3.create("svg")
    .attr("width", width)
    .attr("height", height);

// Add the x-axis.
svg.append("g")
    .attr("transform", `translate(0,${height - marginBottom})`)
    .call(d3.axisBottom(x)
        .ticks(d3.utcYear.every(1))
);

// Add the y-axis.
svg.append("g")
    .attr("transform", `translate(${marginLeft},0)`)
    .call(d3.axisLeft(y));

svg.append("text")
            .attr("class", "x label")
            .attr("text-anchor", "end")
            .attr("x", width/2)
            .attr("y", height - 6)
            .text("Year");

svg.append("text")
            .attr("class", "y label")
            .attr("text-anchor", "end")
            .attr("x", -height/3)
            .attr("y", 6)
            .attr("dy", ".75em")
            .attr("transform", "rotate(-90)")
            .text("Percent of students");           

var heightOfY = height-marginBottom;
var Xmin = 2017;
var Xmax = 2024;
var numTicks = Xmax - Xmin; 
var XmaxRange = width - marginRight - marginLeft;
var eachTickWidth = XmaxRange/numTicks;
var barWidth = eachTickWidth/3;

var arrMMR = [{year: '2017', percent: '1.00'},{year: '2018', percent: '0.98'},{year: '2019', percent: '0.98'},{year: '2021', percent: '1.00'},{year: '2022', percent: '1.00'},{year: '2023', percent: '0.83'},{year: '2024', percent: '1.00'}];

// this single bar works
/*svg.append('rect') 
  .attr('x', marginLeft)
  .attr('y', function() {
      return y(.9)//height/10 * 9) //height = 500, marginBottom = 50 //400
  })
  .attr('width', barWidth)
  .attr('height', function() {
      return ( (.9* height) - marginBottom - 12)
  })
  .attr('fill', 'steelblue');*/

svg.selectAll("mybar") //this doesn't work
  .data(arrMMR)
  .enter()
  .append("rect")
    .attr("x", function(d) { return x(d.year); })
    .attr("y", function(d) { return y(d.percent); })
    .attr("width", x.barWidth)
    .attr("height", function(d) { return height - y(d.percent); })
    .attr("fill", "#69b3a2")


// Append the SVG element.
container.append(svg.node());

</script>

解决方案

It has to do with the way I fed in the data. The percents should have been numbers, not strings. So the data should look like this:

var arrMMR = [{year: '2017', percent: 1.00},{year: '2018', percent: 0.98},{year: '2019', percent: 0.98},{year: '2021', percent: 1.00},{year: '2022', percent: 1.00},{year: '2023', percent: 0.83},{year: '2024', percent: 1.00}];

Then the code to put in the rectangles should treat the years as new Dates:

svg.selectAll("mybar") .data(arrMMR) .enter() .append("rect") .attr("x", function(d) { return x(new Date(d.year)) - (barWidth/2); }) .attr("y", function(d) { return y(d.percent); }) .attr("width", barWidth) .attr("height", function(d) { return heightOfY - y(d.percent); }) .attr("fill", "steelblue")

So the whole code looks like this:

`

// Declare the chart dimensions and margins. const width = 1140; const height = 500; const marginTop = 20; const marginRight = 20; const marginBottom = 50; const marginLeft = 70;

// Declare the x (horizontal position) scale.

const x = d3.scaleUtc() .domain([new Date("2016-01-01"), new Date("2025-01-01")]) .range([marginLeft, width - marginRight]); //same as .range([70,1120])

// Declare the y (vertical position) scale.

const y = d3.scaleLinear() .domain([0, 1.00]) .range([height - marginBottom, marginTop]); //same as .range([350, 20])

// Create the SVG container. const svg = d3.create("svg") .attr("width", width) .attr("height", height);

// Add the x-axis. svg.append("g") .attr("transform", translate(0,${height - marginBottom})) .call(d3.axisBottom(x) .ticks(d3.utcYear.every(1)) );

// Add the y-axis. svg.append("g") .attr("transform", translate(${marginLeft},0)) .call(d3.axisLeft(y));

svg.append("text") .attr("class", "x label") .attr("text-anchor", "end") .attr("x", width/2) .attr("y", height - 6) .text("Year");

svg.append("text") .attr("class", "y label") .attr("text-anchor", "end") .attr("x", -height/3) .attr("y", 6) .attr("dy", ".75em") .attr("transform", "rotate(-90)") .text("Percent of students");

var heightOfY = height-marginBottom; var Xmin = 2017; var Xmax = 2024; var numTicks = Xmax - Xmin; var XmaxRange = width - marginRight - marginLeft; var eachTickWidth = XmaxRange/numTicks; var barWidth = eachTickWidth/3;

var arrMMR = [{year: '2017', percent: 1.00},{year: '2018', percent: 0.98},{year: '2019', percent: 0.98},{year: '2021', percent: 1.00},{year: '2022', percent: 1.00},{year: '2023', percent: 0.83},{year: '2024', percent: 1.00}];

svg.selectAll("mybar") .data(arrMMR) .enter() .append("rect") .attr("x", function(d) { return x(new Date(d.year)) - (barWidth/2); }) .attr("y", function(d) { return y(d.percent); }) .attr("width", barWidth) .attr("height", function(d) { return heightOfY - y(d.percent); }) .attr("fill", "steelblue")

// Append the SVG element. container.append(svg.node());

`

站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章