2016-06-28 2 views
1

Я хочу добавить всплывающие подсказки к прямоугольникам барчара каждый раз, когда мышь входит в прямоугольник, а мышь находится над прямоугольником через несколько миллисекунд. Я также хочу удалить их, когда мышь оставляет какой-либо прямоугольник.D3 показать подсказку на мыши с таймаутом

Я попытался связать его с событиями d3 и использовать setTimeout/clearTimeout.

Это похоже на работу за исключением того, когда вы двигаете мышь быстро через различные бары в то время как линия подсказки переходит,

Проблема в этом случае является, что подсказки перемещается из bar, чтобы bar, что мышь входит/оставляет с учетом таймаута. Текст всплывающей подсказки, похоже, делает некоторые странные вещи.

Позвольте мне показать вам, как появляется подсказка перед тайм-аут:

gif showing the problem

DEMO and FULL CODE at CODEPEN

код для связывания функций, окрашивает всплывающие подсказки:

... 
var bar = svg.select(".bars") 
      .selectAll(".barchart-group") 
      .data(data); 
... 
var come = bar.enter() 
      .append("rect") 
      .style("stroke", undefined) 
      .style("fill", "hsla(34, 82%, 48%, 0.79)"); 
... 
     //bind events to new bars 
     come.on("mouseover", delayTooltip) 
      .on("mouseout", removeBarTooltip); 
... 

кодекса tootlip:

function delayTooltip(d, i) { 
    // this here is every rect of the bar chart 
    this.hoverTimeout = window.setTimeout(addBarTooltip.bind(this), 1000, d, i); 
} 

function addBarTooltip(d, i) { 
    // **** PROBLEM **** 
    // this executes whithout waiting the set timeout 
    var firstAnims = 500; 
    var thisbar = d3.select(this); 
    var tooltip = d3.select(this.parentNode); 
    var gRoot = d3.select(this.parentNode.parentNode); 
    //Lets define some points of interest 
    var p0 = [+thisbar.attr("x") + (barWidth - 1)/2, +thisbar.attr("y")]; 
    var p1 = [p0[0], +p0[1] - 9]; 
    var p2 = [p0[0], +p0[1] - 13]; 
    //relevant points to draw tooltips 
    var line = gRoot.select(".linePointers"); 
    var text = gRoot.select(".textHelpers"); 
    line.append("polyline") 
     .style("stroke-dasharray", "2,1") 
     .style("stroke", "black") 
     .attr("points", [p0, p0]) 
     .transition("line-Y-axis") 
     .duration(firstAnims) 
     .attrTween("points", function(d, i, a) { 
      return d3.interpolate([p0, p0], [p0, p1]); 
     }); 

    text.append("text") 
     .attr("dy", ".2em") 
     .attr("text-anchor", "middle") 
     .attr("x", p2[0]) 
     .attr("y", p1[1]) 
     .text(d.value) 
     .style("font-size", ".85em") 
     .style("opacity", 0) 
     .transition("text-Y-axis") 
     .delay(firstAnims) 
     .duration(300) 
     .style("opacity", 1) 
     .attr("y", p2[1]); 

} 

function removeBarTooltip() { 
    window.clearTimeout(this.hoverTimeout); 
    var firstAnims = 200; 
    var thisbar = d3.select(this); 
    var tooltip = d3.select(this.parentNode); 
    var gRoot = d3.select(this.parentNode.parentNode); 
    //relevant points to draw tooltips 
    var p0 = [+thisbar.attr("x") + (barWidth - 1)/2, +thisbar.attr("y")]; 
    var p1 = [p0[0], +p0[1] - 9]; 
    var p2 = [p0[0], +p0[1] - 13]; 
    //Lets make a group for each part of our tooltip 
    var line = gRoot.select(".linePointers") 
     .selectAll("polyline"); 
    var text = gRoot.select(".textHelpers") 
     .selectAll("text"); 

    line.transition("line-Y-axis") 
     .duration(firstAnims) 
     .attrTween("points", function(d, i, a) { 
      return d3.interpolate([p0, p1], [p0, p0]); 
     }) 
     .remove(); 

    text.style("opacity", 0.7) 
     .transition("text-Y-axis") 
     .delay(firstAnims) 
     .duration(300) 
     .style("opacity", 0) 
     .attr("dy", p0[1] - p2[1]) 
     .remove(); 
} 

Я предпочитаю не добавлять другие библиотеки, если это возможно.

ответ

0

Проблема была в removeBarTooltip(). Давайте сначала посмотрим на этих двух линиях, где я определил точки для tootlip линии:

var p0 = [+thisbar.attr("x") + (barWidth - 1)/2, +thisbar.attr("y")]; 
var p1 = [p0[0], +p0[1] - 9]; 

позже в этой функции я делал:

[...] 
line.transition("line-Y-axis") 
    .duration(firstAnims) 
    .attrTween("points", function(d, i, a) { 
     return d3.interpolate([p0, p1], [p0, p0]); 
    }) 
    .remove(); 

Так что же происходит, что tootlip линия движется от бара до бара из-за значения var p0 в зависимости от того, что мышь закончилась.

Чтобы решить эту проблему, я изменил линию перехода с attrTween к:

line.transition("line-Y-axis") 
    .duration(firstAnims) 
    .attrTween("points", function(d, i, a) { 
     var p0current = a.split(","); 
     var p1current = p0current.splice(2); 
     return d3.interpolate([p0current, p1current], [p0current, p0current]); 
    }) 
    .remove(); 

Где он принимает фактическое значение свойства точек с аргументом a и интерполировать фактическое movemevent основываясь только на нем.

DEMO and FULL code at CODEPEN.

0

Try foxToolTip.js

Есть варианты задержки и длительности перехода как для висения и MouseOut

https://github.com/MichaelRFox/foxToolTip.js

Проверьте мой bl.ock на: http://bl.ocks.org/MichaelRFox/59cdc1c3478fb0362448cf87fdab30d0

Использует 0.5 секунды задержка, чтобы показать всплывающую подсказку при наведении на текстовые элементы

+0

Я хотел бы избежать добавления дополнительных LIBS в мой проект так же, как я могу. Любая идея, что я делаю неправильно? – 40detectives

+0

Ваш bl.ock, похоже, не работает для меня (с того дня, как вы опубликовали), можете ли вы проверить @ m-fox, пожалуйста? – 40detectives