Многострочная линейная диаграмма с подсказкой для мыши

Я создал многострочную линейную диаграмму, используя этот пример кода bl.ocks.org . Мне удалось воссоздать его на JSFiddle .

Многострочная линейная диаграмма

Теперь я пытаюсь добавить всплывающую подсказку x-value mouseover, которая отображает всплывающую подсказку в каждой строке при наведении ее вертикальной позиции. Что-то вроде этого , но для нескольких строк.

Я нашел этот ответ StackOverflow (он включает JSFiddle ), но я не могу заставить его работать с моей многосерийной линейной диаграммой.

svg.append("path") // this is the black vertical line to follow mouse .attr("class","mouseLine") .style("stroke","black") .style("stroke-width", "1px") .style("opacity", "0"); var mouseCircle = causation.append("g") // for each line, add group to hold text and circle .attr("class","mouseCircle"); mouseCircle.append("circle") // add a circle to follow along path .attr("r", 7) .style("stroke", function(d) { console.log(d); return color(d.key); }) .style("fill","none") .style("stroke-width", "1px"); mouseCircle.append("text") .attr("transform", "translate(10,3)"); // text to hold coordinates var bisect = d3.bisector(function(d) { return d.YEAR; }).right; // reusable bisect to find points before/after line svg.append('svg:rect') // append a rect to catch mouse movements on canvas .attr('width', width) // can't catch mouse events on ag element .attr('height', height) .attr('fill', 'none') .attr('pointer-events', 'all') .on('mouseout', function(){ // on mouse out hide line, circles and text d3.select(".mouseLine") .style("opacity", "0"); d3.selectAll(".mouseCircle circle") .style("opacity", "0"); d3.selectAll(".mouseCircle text") .style("opacity", "0"); }) .on('mouseover', function(){ // on mouse in show line, circles and text d3.select(".mouseLine") .style("opacity", "1"); d3.selectAll(".mouseCircle circle") .style("opacity", "1"); d3.selectAll(".mouseCircle text") .style("opacity", "1"); }) .on('mousemove', function() { // mouse moving over canvas d3.select(".mouseLine") .attr("d", function(){ yRange = y.range(); // range of y axis var xCoor = d3.mouse(this)[0]; // mouse position in x var xDate = x.invert(xCoor); // date corresponding to mouse x d3.selectAll('.mouseCircle') // for each circle group .each(function(d,i){ var rightIdx = bisect(data[1].values, xDate); // find date in data that right off mouse var interSect = get_line_intersection(xCoor, // get the intersection of our vertical line and the data line yRange[0], xCoor, yRange[1], x(data[i].values[rightIdx-1].YEAR), y(data[i].values[rightIdx-1].VALUE), x(data[i].values[rightIdx].YEAR), y(data[i].values[rightIdx].VALUE)); d3.select(this) // move the circle to intersection .attr('transform', 'translate(' + interSect.x + ',' + interSect.y + ')'); d3.select(this.children[1]) // write coordinates out .text(xDate.toLocaleDateString() + "," + y.invert(interSect.y).toFixed(0)); }); return "M"+ xCoor +"," + yRange[0] + "L" + xCoor + "," + yRange[1]; // position vertical line }); }); // from here: https://stackoverflow.com/a/1968345/16363 function get_line_intersection(p0_x, p0_y, p1_x, p1_y, p2_x, p2_y, p3_x, p3_y) { var rV = {}; var s1_x, s1_y, s2_x, s2_y; s1_x = p1_x - p0_x; s1_y = p1_y - p0_y; s2_x = p3_x - p2_x; s2_y = p3_y - p2_y; var s, t; s = (-s1_y * (p0_x - p2_x) + s1_x * (p0_y - p2_y)) / (-s2_x * s1_y + s1_x * s2_y); t = ( s2_x * (p0_y - p2_y) - s2_y * (p0_x - p2_x)) / (-s2_x * s1_y + s1_x * s2_y); if (s >= 0 && s = 0 && t <= 1) { // Collision detected rV.x = p0_x + (t * s1_x); rV.y = p0_y + (t * s1_y); } return rV; } 

Итак, проще говоря, я хочу совместить свою линейную диаграмму JSFiddle с этой подсказкой JSFiddle . Кто-нибудь знает, как это сделать? Или есть более простой способ создания всплывающей подсказки? Любая помощь приветствуется!

Вопрос, на который вы ссылались, я ответил еще в апреле. С тех пор я узнал немного больше о SVG и d3 , поэтому я позволю этому служить обновлением этого ответа.

Заметьте, я немного позаимствовал код из превосходного примера кода @ Duopixel.

Вот прокомментированные подробности:

 // append ag for all the mouse over nonsense var mouseG = svg.append("g") .attr("class", "mouse-over-effects"); // this is the vertical line mouseG.append("path") .attr("class", "mouse-line") .style("stroke", "black") .style("stroke-width", "1px") .style("opacity", "0"); // keep a reference to all our lines var lines = document.getElementsByClassName('line'); // here's ag for each circle and text on the line var mousePerLine = mouseG.selectAll('.mouse-per-line') .data(cities) .enter() .append("g") .attr("class", "mouse-per-line"); // the circle mousePerLine.append("circle") .attr("r", 7) .style("stroke", function(d) { return color(d.name); }) .style("fill", "none") .style("stroke-width", "1px") .style("opacity", "0"); // the text mousePerLine.append("text") .attr("transform", "translate(10,3)"); // rect to capture mouse movements mouseG.append('svg:rect') .attr('width', width) .attr('height', height) .attr('fill', 'none') .attr('pointer-events', 'all') .on('mouseout', function() { // on mouse out hide line, circles and text d3.select(".mouse-line") .style("opacity", "0"); d3.selectAll(".mouse-per-line circle") .style("opacity", "0"); d3.selectAll(".mouse-per-line text") .style("opacity", "0"); }) .on('mouseover', function() { // on mouse in show line, circles and text d3.select(".mouse-line") .style("opacity", "1"); d3.selectAll(".mouse-per-line circle") .style("opacity", "1"); d3.selectAll(".mouse-per-line text") .style("opacity", "1"); }) .on('mousemove', function() { // mouse moving over canvas var mouse = d3.mouse(this); // move the vertical line d3.select(".mouse-line") .attr("d", function() { var d = "M" + mouse[0] + "," + height; d += " " + mouse[0] + "," + 0; return d; }); // position the circle and text d3.selectAll(".mouse-per-line") .attr("transform", function(d, i) { console.log(width/mouse[0]) var xDate = x.invert(mouse[0]), bisect = d3.bisector(function(d) { return d.date; }).right; idx = bisect(d.values, xDate); // since we are use curve fitting we can't relay on finding the points like I had done in my last answer // this conducts a search using some SVG path functions // to find the correct position on the line // from http://bl.ocks.org/duopixel/3824661 var beginning = 0, end = lines[i].getTotalLength(), target = null; while (true){ target = Math.floor((beginning + end) / 2); pos = lines[i].getPointAtLength(target); if ((target === end || target === beginning) && pos.x !== mouse[0]) { break; } if (pos.x > mouse[0]) end = target; else if (pos.x < mouse[0]) beginning = target; else break; //position found } // update the text with y value d3.select(this).select('text') .text(y.invert(pos.y).toFixed(2)); // return position return "translate(" + mouse[0] + "," + pos.y +")"; }); }); 

Полный рабочий код:

           
  • Отключение кнопки отправки до тех пор, пока все поля не будут иметь значения
  • Универсальное поле поиска для jqgrid
  • jQuery, изменяющий порядок дочерних элементов
  • Программно создавать список выбора
  • jQuery или CSS-селектор, чтобы выбрать все идентификаторы, начинающиеся с некоторой строки
  • Как я могу получить кнопку, которая вызвала отправку из формы отправить событие?
  • jQuery validate: Как добавить правило для проверки правильности выражения?
  • jquery - разница между $ .functionName и $ .fn.FunctionName
  • Jquery Ajax Загрузка изображения
  • Значение времени ожидания по умолчанию для jQuery ajax
  • jQuery Validate Required Выбрать
  • Давайте будем гением компьютера.