我怎么知道鼠标在D3堆叠条的哪个条中? [英] How do I know which bar the mouse is in for D3 stacked bar?

查看:145
本文介绍了我怎么知道鼠标在D3堆叠条的哪个条中?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在d3中有堆叠条,需要在其中添加工具提示.我很难弄清楚鼠标在哪个栏中,我该如何确定鼠标在哪个栏中?

group.enter().append("g")
         .classed("layer", true)
         .attr("fill", d => z(d.key))
         .on("mouseover", function(d) {
          var num = d.key == "xkey" ? d[4][1] : d[4][1] - d[4][0]
          tip.html("<p>" + d.key + " " + num + "</p>")
            .style("left", (d3.event.pageX) + "px")
            .style("top", (d3.event.pageY - 28) + "px")
            .style("visibility", "visible")
         })
         .on("mouseout", function(d) {
          tip.style("visibility", "hidden")
         });

现在,我只是硬编码以显示最后一个小节的数据.也许我可以玩xScale和事件的x位置?还是这不是D3的方法?

这是pl人: http://plnkr.co/edit/6xB2Kzi46hWL37UjlgTs?p=预览

解决方案

我建议您触发bars上的事件,而不是触发组上的鼠标悬停事件.原因是您在组上的data绑定是按男性和女性堆叠的,因此无法为您提供条形,即Relations.但是,在bars中,如果您在鼠标悬停功能中使用console.log(d),则可以清楚地看到相应的d.data.Relations.

但是,现在代替单个数字,您将获得一个数组,例如[0,70]当您将鼠标悬停在女性上,而[60,130]当您将鼠标悬停在男性上时,表示2002年和其他" Relations的数据.该数组的工作方式是第一个值为当前值,而第二个值为总计.我们可以将此值与d.data中的值进行比较,以评估它是用于性别还是男性.因此,如果d[1]等于numF,即+d.data.Female的值,则它是女性,但如果d[1]等于numF+numM,即(+d.data.Male) + (+d.data.Female)的值之和,则它是雄性,因为在这种情况下,由于keys的顺序为["Female","Male"],因此雄性堆叠在雌性的顶部.

   bars.enter().append("rect")
       .attr("width", xScale.bandwidth())
       .merge(bars)
        .on("mouseover", function(d) {
         console.log(d);
         // get number of females
         let numF = +d.data.Female;
         // get number of males
         let numM = +d.data.Male;
         // get the Relations
         let Relations = d.data.Relations;

         // Evaluate the gender by comparing the mouseover data value for d[1] to the numF for 'Female'
         // or 
         // numF+numM
         let gender,value;
         if (d[1] === numF){
           gender = 'Female';
           value = numF;
         }else if (d[1] === numF+numM) {
           gender = 'Male';
           value = numM;
         }

        //produce the tooltip
        tip.html("<p>" +Relations + "<br>" + gender + ": " + value + "</p>")
        .style("left", (d3.event.pageX) + "px")
        .style("top", (d3.event.pageY - 28) + "px")
        .style("visibility", "visible");
        })
        .on("mouseout", function(d) {
          tip.style("visibility", "hidden");
        })
   .transition().duration(speed)
       .attr("x", d => xScale(d.data.Relations))
       .attr("y", d => yScale(d[1]))
       .attr("height", d => yScale(d[0]) - yScale(d[1]));

请注意,我在RelationsGender: number之间添加了
时,必须更改工具提示的css,使其稍高一些.

将Plunker用作演示.

P.S.为了清晰起见,我还对代码进行了一些清理,例如分号,并将<svg>和工具提示<div>放在<body>内,而不是在其外.

I got stacked bar in d3 and need to add tooltip to it. I have trouble to figure out which bar the mouse is in, any idea how can I decide which bar the mouse is in?

group.enter().append("g")
         .classed("layer", true)
         .attr("fill", d => z(d.key))
         .on("mouseover", function(d) {
          var num = d.key == "xkey" ? d[4][1] : d[4][1] - d[4][0]
          tip.html("<p>" + d.key + " " + num + "</p>")
            .style("left", (d3.event.pageX) + "px")
            .style("top", (d3.event.pageY - 28) + "px")
            .style("visibility", "visible")
         })
         .on("mouseout", function(d) {
          tip.style("visibility", "hidden")
         });

Now I just hardcoded to show the last bar's data. Maybe I can play with xScale and event's x position? Or this is not the D3 way to do it?

Here is the plunker: http://plnkr.co/edit/6xB2Kzi46hWL37UjlgTs?p=preview

解决方案

Instead of triggering mouseover events on the group I suggest you trigger the events on your bars. The reason is that your data bind on the groups is stacked for Male and Female and therefore not able to give you the bar type i.e. Relations. However in your bars if you console.log(d) in the mouseover function you can clearly see the appropriate d.data.Relations.

However, now in place of a single number, you will get an array for e.g. [0,70] when you mouse over for female and [60,130] when you mouse over for male for the data for year 2002 and "Other" Relations. The way this array works is that the first value is the current value, while the second value is the total. We can compare this value to the value from the d.data to evaluate whether it is for the gender Male or Female. So if d[1] is equal to the numF, i.e. the value of +d.data.Female, then it is a female, but if d[1] is equal to numF+numM, i.e. the sum of the value of (+d.data.Male) + (+d.data.Female) then it is a male, as the male is stacked on top of the female in this case due to the order of the keys being ["Female","Male"].

   bars.enter().append("rect")
       .attr("width", xScale.bandwidth())
       .merge(bars)
        .on("mouseover", function(d) {
         console.log(d);
         // get number of females
         let numF = +d.data.Female;
         // get number of males
         let numM = +d.data.Male;
         // get the Relations
         let Relations = d.data.Relations;

         // Evaluate the gender by comparing the mouseover data value for d[1] to the numF for 'Female'
         // or 
         // numF+numM
         let gender,value;
         if (d[1] === numF){
           gender = 'Female';
           value = numF;
         }else if (d[1] === numF+numM) {
           gender = 'Male';
           value = numM;
         }

        //produce the tooltip
        tip.html("<p>" +Relations + "<br>" + gender + ": " + value + "</p>")
        .style("left", (d3.event.pageX) + "px")
        .style("top", (d3.event.pageY - 28) + "px")
        .style("visibility", "visible");
        })
        .on("mouseout", function(d) {
          tip.style("visibility", "hidden");
        })
   .transition().duration(speed)
       .attr("x", d => xScale(d.data.Relations))
       .attr("y", d => yScale(d[1]))
       .attr("height", d => yScale(d[0]) - yScale(d[1]));

Note I had to change the css for the tooltip to make it slightly taller as I added a
between the Relations and the Gender: number.

Working Plunker as a Demo.

P.S. I also cleaned up the code a bit for clarity such as semicolons and placing the <svg> and tooltip <div> within the <body> and not outside of it.

这篇关于我怎么知道鼠标在D3堆叠条的哪个条中?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆