【问题标题】:How to add circle with an on-hover text box to d3.js mulitline chart?如何将带有悬停文本框的圆圈添加到 d3.js 多线图?
【发布时间】:2020-03-05 10:01:11
【问题描述】:

我有一个由两行组成的 d3.js v4 图表。在一条线上(下面的绿色线)我有一个焦点元素,其中一个圆圈在焦点上创建并显示相关数据。

对于橙色线,我希望默认情况下在每个数据点上显示圆圈(不在焦点上),将鼠标悬停在圆圈上应该会在那里显示橙色线的值。

我在网上搜索了解决方案,但我发现的只是单线图表和/或焦点元素,我无法根据我的目的对其进行修改。我可能遇到了 10 个不同的错误,但从未设法让圆圈显示出来。

为了清楚起见,橙色线上的每个数据点都应该有一个圆圈(上面的示例中大约有 20 个数据点),圆圈应该始终显示 - 并且只有在将鼠标悬停在圆圈上时,a文本框应显示包含数据点的值。

这是我当前的代码:

https://jsfiddle.net/a6w89xhj/

橙色线添加为:

eps_data.forEach(function(d) {
    d.date = parseTime(d.date);
    d.value = +d.value;
});

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

g.append("path")
    .data([eps_data])
    .attr('fill', 'none')
    .attr('stroke', '#ff5628')
    .attr("class", "line")
    .attr("d", orangeline);

在此处添加圈子不起作用。出于我的目的,将其添加为焦点元素是不可接受的。所以我被困在这一点上。

【问题讨论】:

    标签: javascript d3.js


    【解决方案1】:

    添加下面的代码会将eps-data线上的每个点用一个圆圈标记:

    g.selectAll().data(eps_data)
        .enter().append("circle")
        .attr("class", "data-circle")
        .attr("r", 5)
        .attr("cx", function(d) { return x(d.date); })
        .attr("cy", function(d) { return y(d.value); })
        .attr('fill', '#ff5628');
    

    这是您的演示的一个分支,应用了以下代码:

    https://jsfiddle.net/ClientsideDesign/e2ky13wt/

    这使用了 d3 的“输入”功能,它为数据集中的每个点提供了一个(空)占位符,然后可以将其附加到(在本例中为一个圆圈)以及根据需要设置样式的任何子元素。

    更多关于在 D3 中具体进入和加入的信息可以找到here

    这是一个额外的演示,两行的鼠标悬停都有值文本:

    https://jsfiddle.net/ClientsideDesign/vcm7puq4/

    我已经在所提供的代码结构内工作,因此可能有整理的余地。行上的最终值似乎没有在悬停时显示,但这可能是故意的?

    在橙色线的每个点上都有一个工具提示:

    g.selectAll().data(eps_data)
      .enter().append("circle")
      .attr("class", "data-circle")
      .attr("r", 5)
      .attr("cx", function (d) { return x(d.date); })
      .attr("cy", function (d) { return y(d.value); })
      .attr('fill', '#ff5628')
      .on("mouseover", function (d) {
        addOrangeTooltip(d, x(d.date), y(d.value));
      });
    
    //...
    
    function addOrangeTooltip(d, x, y) {
      g.append("text")
        .attr("class", "eps-tooltip")
        .style("text-anchor", "middle")
        .text(d.value)
        .attr("x", x)
        .attr("y", y);
    
    // Remove trigger must come after text
    
      g.append("circle")
        .attr("class", "overlay")
        .attr("r", 15)
        .attr("cx", x)
        .attr("cy", y)
        .on("mouseout", function (d) {
          d3.select(this).remove();
          d3.selectAll(".eps-tooltip").remove();
        });
    }
    

    以下链接上的演示。矩形覆盖的鼠标悬停功能需要一些调整才能与 eps-data 行上的鼠标悬停点一起工作:

    https://jsfiddle.net/ClientsideDesign/fvt4c3dz/

    【讨论】:

    • 谢谢马特,我来了。现在看enter 选项,并没有意识到这一点。
    • 这是一个改进,但不是我想要的。我不希望两条线以这种方式连接。目前,悬停在垂直上会显示两行的悬停文本。我需要的是:悬停在圆圈上(不仅仅是垂直的任何地方)仅显示橙色线的悬停文本。否则,只显示绿线的文本,就像在原始示例中一样。
    • 啊,我明白了 - 我会整理一些东西。值得一提的是,这将比它可能更复杂,因为您在整个图表中拥有一个矩形,并带有鼠标悬停事件。
    • 如果我可以在没有它的情况下保持绿线的功能,我很高兴摆脱矩形。
    • 谢谢,看起来不错!我会在早上尝试实现它,我已经离开了我的笔记本电脑。
    【解决方案2】:

    好吧,Matt Saunders 比我快很多……所以我不需要解释太多。

    无论如何,我试图对代码和图表稍加修改,但从概念上讲,它与马特在他的回答中解释的几乎相同。我使用“enter()”函数来创建占位符并用您的数据填充它们。

    这也用于您的货币价值和日期。我没有在悬停时附加文本,而是通过将不透明度设置为 100% 来显示它。

    例如这是用于追加文本,类似于追加圆圈

    svg.selectAll(null).data(data)
        .enter().append('text')
        .attr('x', d => x(d.date) - 22)
        .attr('y', d => y(d.value) - 8)
        .attr('class', (d, i) => 'info-txt data-idx' + i)
        .style('display', d => isNaN(d.value) ? 'none' : null)
        .text(d => d.formatted_date)
    

    在这里找到完整的小提琴:https://jsfiddle.net/Iamnino/6aw9fjLq/39/

    编辑 附带说明:我没有使用您的确切代码。我或多或少是自己写的,所以可能你的一些变量我没有使用...

    【讨论】:

      猜你喜欢
      • 2012-11-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多