d3.js条形图中x轴的起点与y轴截距不对齐

时间:2018-04-15 03:04:36

标签: d3.js charts bar-chart

根据我在网上看到的一些例子创建了一个d3.js条形图,我遇到了一个问题。我想基于x轴将起始数据点与y轴截距对齐。但是,即使经过各种变化(改变scale.ordinal到scale.linear,将变换添加到y轴等),我似乎也无法正确地做到这一点。

同样,我希望x轴上的终点与最后一个数据点对齐。在图表中数据点的开始和开始范围之前和之后都有一个不可见的填充。

我在这里咨询了这个问题,因为它似乎与我的问题相似,但是我的预期结果很简短:D3Js Bar Chart Bars Starting Way After beginning of X-Axis

这是我目前的代码:

var dataUrl = 'https://raw.githubusercontent.com/FreeCodeCamp/ProjectReferenceData/master/GDP-data.json';

// set the dimensions of the canvas
var margin = {
    top: 20,
    right: 20,
    bottom: 70,
    left: 40
  },
  width = 1500 - margin.left - margin.right,
  height = 600 - margin.top - margin.bottom;

// Define the div for the tooltip
var div = d3.select("body").append("div")
  .attr("class", "tooltip")
  .style("opacity", 0);

// set the ranges
var x = d3.scale.ordinal().rangeRoundBands([0, width], 0.01, 1);
var y = d3.scale.linear().range([height, 0]);

// define the axis
var xAxis = d3.svg.axis()
  .scale(x)
  .orient("bottom")
  // Added for the vertical lines (need to remove later)
  .innerTickSize(-height)
  .outerTickSize(0)
  .tickPadding(10);

var yAxis = d3.svg.axis()
  .scale(y)
  .orient("left")
  .ticks(10);

var svg = d3.select(".chart")
  .attr("width", width + margin.left + margin.right)
  .attr("height", height + margin.top + margin.bottom)
  .append("g")
  .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

// load the data
d3.json(dataUrl, function(error, data) {
  data.data.forEach(function(d) {
    d.GDP = d[0];
    d.Year = +d[1];
  });

  // scale the range of the data
  x.domain(data.data.map(function(d) {
    return d.GDP;
  }));
  y.domain([0, d3.max(data.data, function(d) {
    return d.Year;
  })]);

  // add axis
  svg.append("g")
    .attr("class", "x axis")
    .attr("transform", "translate(0," + height + ")")
    .call(xAxis)
    .selectAll("text")
    .style("text-anchor", "end")
    .attr("dx", "-.8em")
    .attr("dy", "-.55em")
    .attr("transform", "rotate(-90)");

  svg.append("g")
    .attr("class", "y axis")
    // .attr("transform", "translate(" + margin.left + ", 0)")
    .call(yAxis)
    .append("text")
    .attr("transform", "rotate(-90)")
    .attr("y", 5)
    .attr("dy", ".71em")
    .style("text-anchor", "end")
    .text("Gross Domestic Product, USA");

  // Add bar chart with tooltip
  svg.selectAll("bar")
    .data(data.data)
    .enter().append("rect")
    .attr("class", "bar")
    .attr("x", function(d) {
      return x(d.GDP);
    })
    .attr("width", x.rangeBand())
    .attr("y", function(d) {
      return y(d.Year);
    })
    .attr("height", function(d) {
      return height - y(d.Year);
    })
    .on("mouseover", function(d) {
      var monthNameFormat = d3.time.format("%b-%Y")
      var gdp_date = monthNameFormat(new Date(d[0]))
      var formatDecimalComma = d3.format(",.2f")
      var curr = formatDecimalComma(d[1])
      div.transition()
        .duration(200)
        .style("opacity", .9);
      div.html(gdp_date + "<br/> $" + curr + " Billion")
        .style("left", (d3.event.pageX) + "px")
        .style("top", (d3.event.pageY - 28) + "px");
    })
    .on("mouseout", function(d) {
      div.transition()
        .duration(500)
        .style("opacity", 0);
    });
});
.chart rect {
  fill: steelblue;
}

.chart text {
  fill: black;
  font: 10px sans-serif;
  text-anchor: middle;
}

bar {
  fill: steelblue;
}

.bar:hover {
  fill: red;
}

.axis {
  font: 10px sans-serif;
}

.axis path,
.axis line {
  fill: none;
  stroke: #000;
  shape-rendering: crispEdges;
}

div.tooltip {
  position: absolute;
  text-align: center;
  width: 130px;
  height: 30px;
  padding: 2px;
  font: 12px sans-serif;
  background: lightsteelblue;
  border: 0px;
  border-radius: 8px;
  pointer-events: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<!-- Source: https://bost.ocks.org/mike/bar/3/ -->
<div id="chart" align="center">
  <svg class="chart"></svg>
</div>

1 个答案:

答案 0 :(得分:1)

rangeRoundBands更改为rangeBands并删除所有填充:

var x = d3.scale.ordinal().rangeBands([0, width]);

以下是您更改的代码:

var dataUrl = 'https://raw.githubusercontent.com/FreeCodeCamp/ProjectReferenceData/master/GDP-data.json';

// set the dimensions of the canvas
var margin = {
    top: 20,
    right: 20,
    bottom: 70,
    left: 40
  },
  width = 1500 - margin.left - margin.right,
  height = 600 - margin.top - margin.bottom;

// Define the div for the tooltip
var div = d3.select("body").append("div")
  .attr("class", "tooltip")
  .style("opacity", 0);

// set the ranges
var x = d3.scale.ordinal().rangeBands([0, width]);
var y = d3.scale.linear().range([height, 0]);

// define the axis
var xAxis = d3.svg.axis()
  .scale(x)
  .orient("bottom")
  // Added for the vertical lines (need to remove later)
  .innerTickSize(-height)
  .outerTickSize(0)
  .tickPadding(10);

var yAxis = d3.svg.axis()
  .scale(y)
  .orient("left")
  .ticks(10);

var svg = d3.select(".chart")
  .attr("width", width + margin.left + margin.right)
  .attr("height", height + margin.top + margin.bottom)
  .append("g")
  .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

// load the data
d3.json(dataUrl, function(error, data) {
  data.data.forEach(function(d) {
    d.GDP = d[0];
    d.Year = +d[1];
  });

  // scale the range of the data
  x.domain(data.data.map(function(d) {
    return d.GDP;
  }));
  y.domain([0, d3.max(data.data, function(d) {
    return d.Year;
  })]);

  // add axis
  svg.append("g")
    .attr("class", "x axis")
    .attr("transform", "translate(0," + height + ")")
    .call(xAxis)
    .selectAll("text")
    .style("text-anchor", "end")
    .attr("dx", "-.8em")
    .attr("dy", "-.55em")
    .attr("transform", "rotate(-90)");

  svg.append("g")
    .attr("class", "y axis")
    // .attr("transform", "translate(" + margin.left + ", 0)")
    .call(yAxis)
    .append("text")
    .attr("transform", "rotate(-90)")
    .attr("y", 5)
    .attr("dy", ".71em")
    .style("text-anchor", "end")
    .text("Gross Domestic Product, USA");

  // Add bar chart with tooltip
  svg.selectAll("bar")
    .data(data.data)
    .enter().append("rect")
    .attr("class", "bar")
    .attr("x", function(d) {
      return x(d.GDP);
    })
    .attr("width", x.rangeBand())
    .attr("y", function(d) {
      return y(d.Year);
    })
    .attr("height", function(d) {
      return height - y(d.Year);
    })
    .on("mouseover", function(d) {
      var monthNameFormat = d3.time.format("%b-%Y")
      var gdp_date = monthNameFormat(new Date(d[0]))
      var formatDecimalComma = d3.format(",.2f")
      var curr = formatDecimalComma(d[1])
      div.transition()
        .duration(200)
        .style("opacity", .9);
      div.html(gdp_date + "<br/> $" + curr + " Billion")
        .style("left", (d3.event.pageX) + "px")
        .style("top", (d3.event.pageY - 28) + "px");
    })
    .on("mouseout", function(d) {
      div.transition()
        .duration(500)
        .style("opacity", 0);
    });
});
.chart rect {
  fill: steelblue;
}

.chart text {
  fill: black;
  font: 10px sans-serif;
  text-anchor: middle;
}

bar {
  fill: steelblue;
}

.bar:hover {
  fill: red;
}

.axis {
  font: 10px sans-serif;
}

.axis path,
.axis line {
  fill: none;
  stroke: #000;
  shape-rendering: crispEdges;
}

div.tooltip {
  position: absolute;
  text-align: center;
  width: 130px;
  height: 30px;
  padding: 2px;
  font: 12px sans-serif;
  background: lightsteelblue;
  border: 0px;
  border-radius: 8px;
  pointer-events: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<!-- Source: https://bost.ocks.org/mike/bar/3/ -->
<div id="chart" align="center">
  <svg class="chart"></svg>
</div>