D3 Grouped Bar Chart - Selecting entire group?

匿名 (未验证) 提交于 2019-12-03 00:57:01

问题:

I have a grouped bar chart similar to https://bl.ocks.org/mbostock/3887051
I used a mouseover function to fade the bars the mouse is currently not over

function mouseover(bar) {    d3.selectAll(".bar")      .filter(function(d){ return (d != bar);})      .transition(t)         .style("opacity", 0.5); } 

While this works nicely to highlight a single bar, I now need to highlight the entire group / fade everything but this group.
So far I haven't been able to figure out though how to get from the datum element d passed via .on("mouseover", function(d) ... back to the entire group this element belongs to.
Is there a simple way to achieve this in D3v4?

回答1:

In D3 4.0 the callback function for the .on() method is passed 3 arguments: the current datum (d), the current index (i), and the current group (nodes).

Within the mouseover callback, you can selectAll("rect"), and filter out items which are in the current group (node). With this selection, you then set opacity to 0.5. On mouseout, you just need to set all opacity back to 1.0. The pertinent code is:

 ...    .on('mouseover', function(d, i, node) {     d3.selectAll("rect")       .filter(function (x) { return !isInArray(this, node)})       .attr('opacity', 0.5);    }   )   .on('mouseout', function() {     d3.selectAll("rect").attr('opacity', 1.0);     }); 

with a small helper function to check if a value is present in an array (array of DOM elements in our case):

 function isInArray(value, array) {      return array.indexOf(value) > -1;  } 

The full code in context (given your linked example):

g.append("g")  .selectAll("g")  .data(data)  .enter().append("g")    .attr("transform", function(d) { return "translate(" + x0(d.State) + ",0)"; })  .selectAll("rect")  .data(function(d) { return keys.map(function(key) { return {key: key, value: d[key]}; }); })  .enter().append("rect")    .attr("x", function(d) { return x1(d.key); })    .attr("y", function(d) { return y(d.value); })    .attr("width", x1.bandwidth())    .attr("height", function(d) { return height - y(d.value); })    .attr("fill", function(d) { return z(d.key); })    .on('mouseover', function(d, i, node) {     d3.selectAll("rect")       .filter(function (x) { return !isInArray(this, node)})       .attr('opacity', 0.5);    }   )   .on('mouseout', function() {     d3.selectAll("rect").attr('opacity', 1.0);     }); 


回答2:

One solution could be:

Make a function which selects all group and gives it a transition of opacity 0.

The DOM on which mouse is over give opacity 1.

  function hoverIn(){     d3.selectAll(".group-me").transition()         .style("opacity", 0.01);//all groups given opacity 0     d3.select(this).transition()         .style("opacity", 1);//give opacity 1 to group on which it hovers.   }   

Make a function which selects all group and gives it a transition of opacity 1, when the mouse is out.

  function hoverOut(){     d3.selectAll(".group-me").transition()         .style("opacity", 1);   }   

On the group add a class and add the mouse out and in function like

  g.append("g")     .selectAll("g")     .data(data)     .enter().append("g")     .classed("group-me", true)//add a class for selection.     .on("mouseover", hoverIn)     .on("mouseout", hoverOut) 

working code here



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!