Несколько графиков на одной странице, ошибка масштаба в D3.js

1

Я новичок в D3.js. Я хотел бы сделать много графиков на одной странице, как здесь http://bl.ocks.org/d3noob/5987480 на основе этого примера https://bl.ocks.org/mbostock/1166403 Изображение 174551

Но у меня возникла проблема. Шкала на первом графике неверна. И я просто не понимаю, почему... Как это исправить?

<!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
Теги:
csv
d3.js

1 ответ

1
Лучший ответ

Ваш масштаб домен установлен, чтобы найти максимальное значение в собственности price, а не свойство close. price - строка, 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 строки сравниваются по аналогии с алфавитным порядком, поэтому строка с наивысшей первой цифрой будет последней (максимум, см. Этот ответ или этот для получения дополнительной информации о сравнении строк). В вашем случае это 960, так как вы можете увидеть, включили ли вы эту строку после того, как вы установили домен:

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

Вместо этого просто измените свой домен масштаба на:

 y.domain([0, d3.max(data, function(d) { return d.close; })]);
  • 0
    Большое спасибо! Работал!

Ещё вопросы

Сообщество Overcoder
Наверх
Меню