Nano Hash - криптовалюты, майнинг, программирование

D3.js: при наведении курсора на несколько линейных диаграмм с одним и тем же x (время) отображаются разные y (цена)

Я пытаюсь объединить два примера D3.js, которые я нашел здесь bl.ocks.org/mbostock/1157787 (множественный пример) и здесь bl.ocks.org/mbostock/3902569 (пример при наведении курсора).

Пока все работает как задумано. Фокус при наведении курсора связан со всеми графиками через x (время), отображая значения цен на каждом отдельном графике одновременно. Однако отображаемое значение и позиция устанавливаются данными последней диаграммы, показывающими неправильные позиции и значения на всех других диаграммах. Я пытаюсь понять, как обращаться с каждой отдельной диаграммой с ее собственными значениями и позициями фокуса. Я нашел несколько похожих вопросов, касающихся нескольких диаграмм и нескольких положений фокуса при наведении курсора, но не двух тем вместе взятых. Я новичок в JS и D3, поэтому не знаю, как присвоить правильные значения правильному объекту фокуса. См. здесь http://plnkr.co/edit/btAPsU0ra6uR3f4ZXZWj. Вот мой код

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

body {
  font: 10px sans-serif;
  margin: 0;
}

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

.line {
  fill: none;
  stroke: steelblue;
  stroke-width: 1.5px;
}

.area {
  //fill: #e7e7e7;
  fill: transparent;
}

.overlay {
  fill: none;
  pointer-events: all;
}

.focus circle {
  fill: none;
  stroke: steelblue;
}
</style>
<body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js"></script>
<script>

var margin = {top: 8, right: 10, bottom: 20, left: 30},
    width = 960 - margin.left - margin.right,
    height = 138 - margin.top - margin.bottom;

var parseDate = d3.time.format("%b %Y").parse,
    bisectDate = d3.bisector(function(d) { return d.date; }).left,
    formatValue = d3.format(",.2f"),
    formatCurrency = function(d) { return formatValue(d); };

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

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

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

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

var xAxis = d3.svg.axis()
  .scale(x)         // x is the d3.time.scale()
  .orient("bottom") // the ticks go below the graph
  .ticks(4);        // specify the number of ticks

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

d3.csv("stocks_chart2.csv", type, function(error, data) {

    // Nest data by symbol.
    var symbols = d3.nest()
      .key(function(d) { return d.symbol; })
      .entries(data);

    // Compute the maximum price per symbol, needed for the y-domain.
    symbols.forEach(function(s) {
    s.maxPrice = d3.max(s.values, function(d) { return d.price; });
    });

    // Compute the minimum and maximum date across symbols.
    // We assume values are sorted by date.
    x.domain([
    d3.min(symbols, function(s) { return s.values[0].date; }),
    d3.max(symbols, function(s) { return s.values[s.values.length - 1].date; })
    ]);

    // Add an SVG element for each symbol, with the desired dimensions and margin.
    var svg = d3.select("body").selectAll("svg")
      .data(symbols)
    .enter().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 + ")");

    // Add the area path elements. Note: the y-domain is set per element.
    svg.append("path")
      .attr("class", "area")
      .attr("d", function(d) { y.domain([0, d.maxPrice]); return area(d.values); });

    // Add the line path elements. Note: the y-domain is set per element.
    svg.append("path")
      .attr("class", "line")
      .attr("d", function(d) { y.domain([0, d.maxPrice]); return line(d.values); });

    // Add a small label for the symbol name.
    svg.append("text")
      .attr("x", width - 6)
      .attr("y", height - 6)
      .style("text-anchor", "end")
      .text(function(d) { return d.key; });

    svg.append('g')            // create a <g> element
      .attr('class', 'x axis') // specify classes
      .attr("transform", "translate(0," + height + ")") 
      .call(xAxis);            // let the axis do its thing

    svg.append("g")
      .attr("class", "y axis")
      .call(yAxis)
    .append("text")
      .attr("transform", "rotate(-90)")
      .attr("y", 6)
      .attr("dy", ".71em")
      .style("text-anchor", "end")
      .text("Value");

    var focus = svg.append("g")
      .attr("class", "focus")
      .style("display", "none");

    focus.append("circle")
      .attr("r", 4.5);

    focus.append("text")
      .attr("x", 9)
      .attr("dy", ".35em");

    svg.append("rect")
      .attr("class", "overlay")
      .attr("width", width)
      .attr("height", height)
      .on("mouseover", function() { focus.style("display", null); })
      .on("mouseout", function() { focus.style("display", "none"); })
      .on("mousemove", mousemove);

  function mousemove() {
    var x0 = x.invert(d3.mouse(this)[0]),
        i = bisectDate(data, x0, 1),
        d0 = data[i - 1],
        d1 = data[i],
        d = x0 - d0.date > d1.date - x0 ? d1 : d0;
    focus.attr("transform", "translate(" + x(d.date) + "," + y(d.price) + ")");
    focus.select("text").text(formatCurrency(d.price));
  }

});

function type(d) {
  d.price = +d.price;
  d.date = parseDate(d.date);
  return d;
}

</script>

и data.csv, использованный в примере с кратными числами (сокращенный)

symbol,date,price
S&P 500,Jan 2000,1394.46
S&P 500,Feb 2000,1366.42
S&P 500,Mar 2000,1498.58
S&P 500,Apr 2000,1452.43
S&P 500,May 2000,1420.6
S&P 500,Jun 2000,1454.6
S&P 500,Jul 2000,1430.83
S&P 500,Aug 2000,1517.68
S&P 500,Sep 2000,1436.51
S&P 500,Oct 2000,1429.4
S&P 500,Nov 2000,1314.95
S&P 500,Dec 2000,1320.28
S&P 500,Jan 2001,1366.01
S&P 500,Feb 2001,1239.94
S&P 500,Mar 2001,1160.33
S&P 500,Apr 2001,1249.46
S&P 500,May 2001,1255.82
S&P 500,Jun 2001,1224.38
S&P 500,Jul 2001,1211.23
S&P 500,Aug 2001,1133.58
S&P 500,Sep 2001,1040.94
S&P 500,Oct 2001,1059.78
S&P 500,Nov 2001,1139.45
S&P 500,Dec 2001,1148.08
S&P 500,Jan 2002,1130.2
S&P 500,Feb 2002,1106.73
S&P 500,Mar 2002,1147.39
S&P 500,Apr 2002,1076.92
S&P 500,May 2002,1067.14
S&P 500,Jun 2002,989.82
S&P 500,Jul 2002,911.62
S&P 500,Aug 2002,916.07
S&P 500,Dec 2008,903.25
S&P 500,Jan 2009,825.88
S&P 500,Feb 2009,735.09
S&P 500,Mar 2009,797.87
S&P 500,Apr 2009,872.81
S&P 500,May 2009,919.14
S&P 500,Jun 2009,919.32
S&P 500,Jul 2009,987.48
S&P 500,Aug 2009,1020.62
S&P 500,Sep 2009,1057.08
S&P 500,Oct 2009,1036.19
S&P 500,Nov 2009,1095.63
S&P 500,Dec 2009,1115.1
S&P 500,Jan 2010,1073.87
S&P 500,Feb 2010,1104.49
S&P 500,Mar 2010,1140.45
MSFT,Jan 2000,39.81
MSFT,Feb 2000,36.35
MSFT,Mar 2000,43.22
MSFT,Apr 2000,28.37
MSFT,May 2000,25.45
MSFT,Jun 2000,32.54
MSFT,Jul 2000,28.4
MSFT,Aug 2000,28.4
MSFT,Sep 2000,24.53
MSFT,Oct 2000,28.02
MSFT,Nov 2000,23.34
MSFT,Dec 2000,17.65
MSFT,Jan 2001,24.84
MSFT,Feb 2001,24
MSFT,Mar 2001,22.25
MSFT,Apr 2001,27.56
MSFT,Aug 2009,24.43
MSFT,Sep 2009,25.49
MSFT,Oct 2009,27.48
MSFT,Nov 2009,29.27
MSFT,Dec 2009,30.34
MSFT,Jan 2010,28.05
MSFT,Feb 2010,28.67
MSFT,Mar 2010,28.8
AMZN,Jan 2000,64.56
AMZN,Feb 2000,68.87
AMZN,Mar 2000,67
AMZN,Apr 2000,55.19
AMZN,May 2000,48.31
AMZN,Jun 2000,36.31
AMZN,Jul 2000,30.12
AMZN,Aug 2000,41.5
AMZN,Sep 2000,38.44
AMZN,Oct 2000,36.62
AMZN,Nov 2000,24.69
AMZN,Dec 2000,15.56
AMZN,Jan 2001,17.31
AMZN,Feb 2001,10.19
AMZN,Mar 2001,10.23
AMZN,Apr 2001,15.78
AMZN,May 2001,16.69
AMZN,Jun 2001,14.15
AMZN,Jul 2001,12.49
AMZN,May 2007,69.14
AMZN,Jun 2007,68.41
AMZN,Jul 2007,78.54
AMZN,Aug 2007,79.91
AMZN,Sep 2007,93.15
AMZN,Oct 2007,89.15
AMZN,Nov 2007,90.56
AMZN,Dec 2007,92.64
AMZN,Jan 2008,77.7
AMZN,Feb 2008,64.47
AMZN,Mar 2008,71.3
AMZN,Apr 2008,78.63
AMZN,May 2008,81.62
AMZN,Jun 2008,73.33
AMZN,Jul 2008,76.34
AMZN,Aug 2008,80.81
AMZN,Sep 2008,72.76
AMZN,Oct 2008,57.24
AMZN,Nov 2008,42.7
AMZN,Dec 2008,51.28
AMZN,Jan 2009,58.82
AMZN,Feb 2009,64.79
AMZN,Mar 2009,73.44
AMZN,Apr 2009,80.52
AMZN,May 2009,77.99
AMZN,Jun 2009,83.66
AMZN,Jul 2009,85.76
AMZN,Aug 2009,81.19
AMZN,Sep 2009,93.36
AMZN,Oct 2009,118.81
AMZN,Nov 2009,135.91
AMZN,Dec 2009,134.52
AMZN,Jan 2010,125.41
AMZN,Feb 2010,118.4
AMZN,Mar 2010,128.82
IBM,Jan 2000,100.52
IBM,Feb 2000,92.11
IBM,Mar 2000,106.11
IBM,Jun 2003,75.42
IBM,Jul 2003,74.28
IBM,Aug 2003,75.12
IBM,Sep 2003,80.91
IBM,Mar 2009,95.09
IBM,Apr 2009,101.29
IBM,May 2009,104.85
IBM,Jun 2009,103.01
IBM,Jul 2009,116.34
IBM,Aug 2009,117
IBM,Sep 2009,118.55
IBM,Oct 2009,119.54
IBM,Nov 2009,125.79
IBM,Dec 2009,130.32
IBM,Jan 2010,121.85
IBM,Feb 2010,127.16
IBM,Mar 2010,125.55
GOOG,Aug 2004,102.37
GOOG,Sep 2004,129.6
GOOG,Oct 2004,190.64
GOOG,Nov 2004,181.98
GOOG,Dec 2004,192.79
GOOG,Jan 2005,195.62
GOOG,Feb 2005,187.99
GOOG,Mar 2005,180.51
GOOG,Apr 2005,220
GOOG,May 2005,277.27
GOOG,Jun 2005,294.15
GOOG,Jul 2005,287.76
GOOG,Aug 2005,286
GOOG,Sep 2005,316.46
GOOG,Oct 2005,372.14
GOOG,Nov 2005,404.91
GOOG,Dec 2005,414.86
GOOG,Jan 2006,432.66
GOOG,Feb 2006,362.62
GOOG,Mar 2006,390
GOOG,Apr 2006,417.94
GOOG,May 2006,371.82
GOOG,Jun 2006,419.33
GOOG,Jul 2006,386.6
GOOG,Aug 2006,378.53
GOOG,Sep 2006,401.9
GOOG,Oct 2006,476.39
GOOG,Nov 2006,484.81
GOOG,Jul 2009,443.05
GOOG,Aug 2009,461.67
GOOG,Sep 2009,495.85
GOOG,Oct 2009,536.12
GOOG,Nov 2009,583
GOOG,Dec 2009,619.98
GOOG,Jan 2010,529.94
GOOG,Feb 2010,526.8
GOOG,Mar 2010,560.19
10 Year T-Note,Jan 2000,6.67
10 Year T-Note,Feb 2000,6.41
10 Year T-Note,Mar 2000,6.02
10 Year T-Note,Apr 2000,6.21
10 Year T-Note,May 2000,6.28
10 Year T-Note,Jun 2000,6.02
10 Year T-Note,Jul 2000,6.03
10 Year T-Note,Aug 2000,5.73
10 Year T-Note,Sep 2000,5.78
10 Year T-Note,Oct 2000,5.76
10 Year T-Note,Nov 2000,5.44
10 Year T-Note,Dec 2000,5.11
10 Year T-Note,Jan 2001,5.18
10 Year T-Note,Feb 2001,4.91
10 Year T-Note,Mar 2001,4.91
10 Year T-Note,Apr 2001,5.34
10 Year T-Note,May 2001,5.41
10 Year T-Note,Jun 2001,5.39
10 Year T-Note,Jul 2001,5.04
10 Year T-Note,Aug 2001,4.82
10 Year T-Note,Sep 2001,4.57
AAPL,Jan 2000,25.94
AAPL,Feb 2000,28.66
AAPL,Mar 2000,33.95
AAPL,Apr 2000,31.01
AAPL,May 2000,21
AAPL,Jun 2000,26.19
AAPL,Jul 2000,25.41
AAPL,Aug 2000,30.47
AAPL,Sep 2000,12.88
AAPL,Oct 2000,9.78
AAPL,Nov 2000,8.25
AAPL,Dec 2000,7.44
AAPL,Jan 2001,10.81
AAPL,Feb 2001,9.12
AAPL,Mar 2001,11.03
AAPL,Apr 2001,12.74
AAPL,May 2001,9.98

Любая помощь будет принята с благодарностью! Благодарю вас!

11.09.2015

Ответы:


1

У меня это не работает идеально, но я считаю, что это должно помочь вам начать. Причина того, что то, что вы делаете, не работает, заключается в том, что вы делитесь фрагментом данных d со всеми диаграммами.

function mousemove() {
    var date = x.invert(d3.mouse(this)[0]),
        index = bisectDate(data, date, 1),
        d0 = data[index - 1],
        d1 = data[index],
        d = date - d0.date > d1.date - date ? d1 : d0;
    focus.attr("transform", "translate(" + x(d.date) + "," + y(d.price) + ")");
    focus.select("text").text(formatCurrency(d.price));

Итак, этот кусок кода здесь выбирает все элементы focus, которые вы используете для своих всплывающих подсказок, но применяет отформатированную валюту для d.price. Однако, если вы посмотрите на это, d, который управляет ценой, исходит непосредственно из данных от движения мыши.

Вместо этого вам нужно назначить данные для каждого элемента фокуса отдельно. К сожалению, у меня это не совсем работает, так как я не отследил, как рассчитывается index, но это дает представление:

function mousemove() {
   var date = x.invert(d3.mouse(this)[0]),
    index = bisectDate(data, date, 1),
    d0 = data[index - 1],
    d1 = data[index],
    d = date - d0.date > d1.date - date ? d1 : d0;

    var focus = svg.selectAll(".focus");

    focus.attr("translate", function(d) {
      return "translate(" + x(d.values[index].date) + "," + y(d.values[index].price) + ")"
    });

    focus.selectAll("text", function(d) {
      return formatCurrency(d.values[index].price);
    });
}

Итак, что здесь происходит, так это то, что каждый из focus элементов имеет свой перевод и текст, установленный специально на основе данных, которые управляют этой серией. Параметр d теперь ограничен (и будет предоставлен автоматически из D3 после предыдущей привязки данных) к этим функциям и будет использоваться для доступа к фактическим данным, которые вам нужны.

14.09.2015
  • Большое спасибо! Я делаю успехи. Кажется, я собираю правильные значения (см. console.log ниже). Однако функция преобразования/перевода атрибута фокуса, а также его текстовый атрибут кажутся неработающими, хотя значения кажутся правильными. Любые подсказки? См. plnkr.co/edit/u6OsFvnDDt4jwljyVyr5?p=preview. Благодарю вас! 15.09.2015
  • @Kai У тебя неправильный индекс. Он показывает неправильные значения для меня (а также, кажется, только часть набора данных, когда я нахожусь в крайнем правом графике. 15.09.2015
  • Вы правы, это проблема, о которой я говорил. Когда я закомментирую строку 163: return translate [...] index и значения, видимые console.log, в порядке (см. plnkr.co/edit/u6OsFvnDDt4jwljyVyr5?p=preview). Что-то происходит с обратным переводом [...] Я не могу понять 15.09.2015
  • На самом деле наведение мыши работает нормально, это линия диаграммы, которая неправильно отображает значения на некоторых диаграммах. 16.09.2015
  • Новые материалы

    Кластеризация: более глубокий взгляд
    Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

    Как написать эффективное резюме
    Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

    Частный метод Python: улучшение инкапсуляции и безопасности
    Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

    Как я автоматизирую тестирование с помощью Jest
    Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

    Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
    Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

    Понимание расстояния Вассерштейна: мощная метрика в машинном обучении
    В обширной области машинного обучения часто возникает необходимость сравнивать и измерять различия между распределениями вероятностей. Традиционные метрики расстояния, такие как евклидово..

    Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
    В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..