【问题标题】:D3 show tooltip on mouse over with a timeoutD3 在鼠标悬停时显示工具提示并超时
【发布时间】:2016-06-28 13:31:16
【问题描述】:

每当鼠标进入一个矩形并且鼠标在几毫秒后鼠标悬停在矩形上时,我想向条形的矩形添加工具提示。当鼠标离开任何矩形时,我也想删除它们。

我尝试将它与 d3 事件绑定并使用 setTimeout/clearTimeout。

它似乎可以工作除非你在工具提示行转换时快速移动鼠标通过不同的条,

问题在这种情况下鼠标进入/离开的工具提示从一个栏移动到另一个栏 忽略超时。工具提示的文本似乎确实做了一些奇怪的事情。

让我告诉你在超时之前工具提示是如何出现的:

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();
}

如果可能,我宁愿避免添加任何其他库。

【问题讨论】:

    标签: d3.js mouseevent settimeout transition mouseenter


    【解决方案1】:

    问题出在removeBarTooltip()。让我们先看看这两行,我在其中定义了提示线的点:

    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();
    

    所以发生的情况是,由于 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 获取points 属性的实际值,并仅基于它插入实际的movemevent。

    DEMO and FULL code at CODEPEN.

    【讨论】:

      【解决方案2】:

      试试 foxToolTip.js

      具有悬停和鼠标悬停的延迟和过渡持续时间选项

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

      查看我的 bl.ock:http://bl.ocks.org/MichaelRFox/59cdc1c3478fb0362448cf87fdab30d0

      将鼠标悬停在文本元素上时使用 0.5 秒延迟显示工具提示

      【讨论】:

      • 我想尽可能避免向我的项目添加更多库。知道我做错了什么吗?
      • 您的 bl.ock 似乎对我不起作用(从您发布的那天起),请您检查一下@m-fox,好吗?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-04-22
      • 2011-09-30
      • 1970-01-01
      • 2013-04-07
      • 1970-01-01
      相关资源
      最近更新 更多