一页上有多个图表,D3.js中的比例错误

时间:2017-06-01 17:29:13

标签: javascript csv d3.js

我是D3.js的新手。我想基于此示例http://bl.ocks.org/d3noob/5987480在一个页面上制作许多图表https://bl.ocks.org/mbostock/1166403 enter image description here

但我遇到了一个问题。第一个图表中的比例不正确。我只是不明白,为什么......如何解决这个问题?

<!DOCTYPE html>
<meta charset="utf-8">
<style>

svg {
  font: 12px Arial;
}

path.line {
  fill: none;
  stroke: #666;
  stroke-width: 1.5px;
}

path.area {
  fill: #e7e7e7;
}

.axis {
  shape-rendering: crispEdges;
}

.x.axis line {
  stroke: #fff;
}

.x.axis .minor {
  stroke-opacity: .5;
}

.x.axis path {
  display: none;
}

.y.axis line,
.y.axis path {
  fill: none;
  stroke: #000;
}

</style>
<body>
<div id="area1"></div>
<script src="http://d3js.org/d3.v3.min.js"></script>
<script>

var margin = {top: 10, right: 20, bottom: 20, left: 40},
    width = 300 - margin.left - margin.right,
    height = 150 - margin.top - margin.bottom;

var parse = d3.time.format("%Y").parse;

var x = d3.time.scale()
    .range([0, width]);

var y = d3.scale.linear()
    .range([height, 0]);

var xAxis = d3.svg.axis()
    .scale(x)
    .ticks(8)
    .tickSize(-height);

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

var area = d3.svg.area()
    .interpolate("monotone")
    .x(function(d) { return x(d.date); })
    .y0(height)
    .y1(function(d) { return y(d.price); });

var line = d3.svg.line()
    .interpolate("monotone")
    .x(function(d) { return x(d.date); })
    .y(function(d) { return y(d.price); });

var svg1 = d3.select("#area1").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 + ")");

svg1.append("clipPath")
    .attr("id", "clip")
  .append("rect")
    .attr("width", width)
    .attr("height", height);

d3.csv("1-1.9.csv", function(error, data) {
    data.forEach(function(d) {
        d.date = parse(d.date);
        d.close = +d.price;
    });

    // Scale the range of the data
    x.domain(d3.extent(data, function(d) { return d.date; }));
    y.domain([0, d3.max(data, function(d) { return d.price; })]);
    area.y0(y(0));

  svg1
      .datum(data);

  svg1.append("path")
      .attr("class", "area")
      .attr("clip-path", "url(#clip)")
      .attr("d", area);

  svg1.append("g")
      .attr("class", "x axis")
      .attr("transform", "translate(0," + height + ")")
      .call(xAxis);

  svg1.append("g")
      .attr("class", "y axis")
      .call(yAxis);

  svg1.append("path")
      .attr("class", "line")
      .attr("clip-path", "url(#clip)")
      .attr("d", line);

  svg1.append("text")
      .attr("x", width - 6)
      .attr("y", height - 6)
      .style("text-anchor", "end")
      .text(data[0].symbol);


});

var svg2 = d3.select("#area1").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 + ")");

svg2.append("clipPath")
    .attr("id", "clip")
  .append("rect")
    .attr("width", width)
    .attr("height", height);

d3.csv("2-2.9.csv", function(error, data) {
    data.forEach(function(d) {
        d.date = parse(d.date);
        d.close = +d.price;
    });

    // Scale the range of the data
    x.domain(d3.extent(data, function(d) { return d.date; }));
    y.domain([0, d3.max(data, function(d) { return d.price; })]);
    area.y0(y(0));

  svg2
      .datum(data);

  svg2.append("path")
      .attr("class", "area")
      .attr("clip-path", "url(#clip)")
      .attr("d", area);

  svg2.append("g")
      .attr("class", "x axis")
      .attr("transform", "translate(0," + height + ")")
      .call(xAxis);

  svg2.append("g")
      .attr("class", "y axis")
      .call(yAxis);

  svg2.append("path")
      .attr("class", "line")
      .attr("clip-path", "url(#clip)")
      .attr("d", line);

  svg2.append("text")
      .attr("x", width - 6)
      .attr("y", height - 6)
      .style("text-anchor", "end")
      .text(data[0].symbol);


});

</script>

1-1.9.csv:

symbol,date,price
1-1.9,2003,339
1-1.9,2004,560
1-1.9,2005,792
1-1.9,2006,2579
1-1.9,2007,960
1-1.9,2008,3295
1-1.9,2009,3807
1-1.9,2010,2634
1-1.9,2011,2576
1-1.9,2012,2748
1-1.9,2013,4292
1-1.9,2014,4295
1-1.9,2015,4045

2-2.9.csv:

symbol,date,price
2-2.9,2003,1768
2-2.9,2004,1732
2-2.9,2005,1714
2-2.9,2006,2622
2-2.9,2007,2281
2-2.9,2008,3801
2-2.9,2009,3712
2-2.9,2010,3407
2-2.9,2011,3349
2-2.9,2012,3237
2-2.9,2013,5180
2-2.9,2014,3496
2-2.9,2015,3076

1 个答案:

答案 0 :(得分:1)

您的比例域设置为在属性price中找到最大值,而不是属性closeprice是一个字符串,close是一个整数。

您的数据数组包含以下对象:

{ symbol: "1-1.9", date: Date 2006-01-01T08:00:00.000Z, price: "2579", close: 2579 } 
{ symbol: "1-1.9", date: Date 2007-01-01T08:00:00.000Z, price: "960", close: 960 }

比较价格会比较字符串。在javascript中,字符串以类似于字母顺序的方式进行比较,因此具有最高第一个数字的字符串将是最后一个(最大值,请参阅this answerthis one以获取有关比较字符串的更多信息)。在您的情况下,即960,您可以看到在设置域后是否包含此行:

console.log(y.domain()); // [0,960]

相反,只需将您的比例域更改为:

 y.domain([0, d3.max(data, function(d) { return d.close; })]);