【问题标题】:Hightlight the respective layer in stacked Bar chart when mouseover on legend in d3当鼠标悬停在 d3 中的图例上时,突出显示堆叠条形图中的相应图层
【发布时间】:2023-03-16 13:55:01
【问题描述】:

我已经完成了一个堆积条形图,现在我正在扩展图表功能,因为当鼠标悬停在图例上时,相应的条形应该突出显示。

我面临的问题是鼠标悬停事件仅适用于最后一个图例,但突出显示图表中的每个矩形层。

问题如下图所示。此图像是我将鼠标悬停在 D_Lines Legend Rect 上时

我的代码部分是

var svg = d3.select("body")
  .append("svg")
  .attr("width", width + margin.left + margin.right)
  .attr("height", height + margin.top + margin.bottom)
  .append("g")
  .attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var fData = 

[{"orders":"A","Total_Orders":76,"A_Lines":123,"B_Lines":0,"C_Lines":0,"D_Lines":0,"Total_Lines":123,"Total_Units":3267},
{"orders":"B","Total_Orders":68,"A_Lines":0,"B_Lines":107,"C_Lines":0,"D_Lines":0,"Total_Lines":107,"Total_Units":3115},
{"orders":"C","Total_Orders":81,"A_Lines":0,"B_Lines":0,"C_Lines":123,"D_Lines":0,"Total_Lines":123,"Total_Units":3690},
{"orders":"D","Total_Orders":113,"A_Lines":0,"B_Lines":0,"C_Lines":0,"D_Lines":203,"Total_Lines":203,"Total_Units":7863},
{"orders":"AB","Total_Orders":62,"A_Lines":70,"B_Lines":76,"C_Lines":0,"D_Lines":0,"Total_Lines":146,"Total_Units":1739},
{"orders":"AC","Total_Orders":64,"A_Lines":77,"B_Lines":0,"C_Lines":79,"D_Lines":0,"Total_Lines":156,"Total_Units":2027},
{"orders":"AD","Total_Orders":100,"A_Lines":127,"B_Lines":0,"C_Lines":0,"D_Lines":144,"Total_Lines":271,"Total_Units":6467},
{"orders":"BC","Total_Orders":64,"A_Lines":0,"B_Lines":80,"C_Lines":84,"D_Lines":0,"Total_Lines":164,"Total_Units":1845},
{"orders":"BD","Total_Orders":91,"A_Lines":0,"B_Lines":108,"C_Lines":0,"D_Lines":135,"Total_Lines":243,"Total_Units":4061},
{"orders":"CD","Total_Orders":111,"A_Lines":0,"B_Lines":0,"C_Lines":132,"D_Lines":147,"Total_Lines":279,"Total_Units":5011},
{"orders":"ABC","Total_Orders":45,"A_Lines":58,"B_Lines":63,"C_Lines":55,"D_Lines":0,"Total_Lines":176,"Total_Units":1245},
{"orders":"ABD","Total_Orders":69,"A_Lines":105,"B_Lines":87,"C_Lines":0,"D_Lines":116,"Total_Lines":308,"Total_Units":4538},
{"orders":"ACD","Total_Orders":66,"A_Lines":91,"B_Lines":0,"C_Lines":88,"D_Lines":132,"Total_Lines":311,"Total_Units":4446},{
{"orders":"BCD","Total_Orders":68,"A_Lines":0,"B_Lines":84,"C_Lines":95,"D_Lines":111,"Total_Lines":290,"Total_Units":4187},
{"orders":"ABCD","Total_Orders":56,"A_Lines":96,"B_Lines":90,"C_Lines":93,"D_Lines":143,"Total_Lines":422,"Total_Units":6331}] 

var headers = ["A_Lines", "B_Lines", "C_Lines", "D_Lines"];

        var layers = d3.layout.stack()(headers.map(function (count) {
            return fData.map(function (d) {
                // alert(d);
                return { x: d.ORDER_TYPE, y: +d[count] };
            });
        }));
        //StackedBar Rectangle Max

        var yStackMax = d3.max(layers, function (layer) { return d3.max(layer, function (d) { return d.y0 + d.y; }); });
        // Set x, y and colors
        var xScale = d3.scale.ordinal()
     .domain(layers[0].map(function (d) { return d.x; }))
     .rangeRoundBands([25, width], .08);
        colors = ["#9999CC", "#F7A35C", "#99CC99", "#CCCC99"];
        var y = d3.scale.linear()
            .domain([0, yStackMax])
            .range([height, 0]);
        var colorScale = d3.scale.ordinal()
    .domain(headers)
     .range(colors);

        // Define and draw axes
        var xAxis = d3.svg.axis()
                    .scale(xScale)
                    .tickSize(1)
                    .tickPadding(6)
                    .orient("bottom");

        var yAxis = d3.svg.axis()
                    .scale(y)
                    .orient("left")
                    .tickFormat(d3.format(".2s"))



        var layer = svg.selectAll(".layer")
            .data(layers)
            .enter().append("g")
            .attr("class", "layer")
            .style("fill", function (d, i) { return colorScale(i); });

        var rect = layer.selectAll("rect")
            .data(function (d) { return d; })
            .enter().append("rect")
            .attr("x", function (d) { return xScale(d.x); })
            .attr("y", height)
            .attr("width", xScale.rangeBand())
            .attr("height", 0)
             .attr("class", function (d) {
                 return "rect bordered " + "color-" + colorScale(d.value).substring(1);
             });
        debugger;
        layer.selectAll("text.rect")
            .data(function (layer) { return layer; })
            .enter().append("text")
            .attr("text-anchor", "middle")
            .attr("x", function (d) { return xScale(d.x) + xScale.rangeBand() / 2; })
            .attr("y", function (d) { return y(d.y + d.y0) - 3; })
            .text(function (d) { return d.y + d.y0; })
            .style("fill", "4682b4");

        //********** AXES ************

        svg.append("g")
             .attr("class", "x axis")
             .attr("transform", "translate(0," + height + ")")
             .call(xAxis)
             .selectAll("text").style("text-anchor", "end")
                 .attr("dx", "-.8em")
                 .attr("dy", ".15em")
                 .attr("transform", function (d) {
                     return "rotate(-45)"
                 });

        svg.attr("class", "x axis")
           .append("text")
           .attr("text-anchor", "end")  // this makes it easy to centre the text as the transform is applied to the anchor
           .attr("transform", "translate(" + (width / 2) + "," + (height + 60) + ")")  // centre below axis
           .text("Order Velocity Group");


        svg.append("g")
            .attr("class", "y axis")
            .attr("transform", "translate(20,0)")
            .call(yAxis)
          .append("text")
            .attr("transform", "rotate(-90)")
            .attr({ "x": -75, "y": -70 })
            .attr("dy", ".75em")
            .style("text-anchor", "end")
            .text("No. Of Lines");

        //********** LEGEND ************
        var legend = svg.selectAll(".legend")
                    .data(headers.slice().reverse())
                .enter().append("g")
                .attr("class", "legend")
                .attr("transform", function (d, i) { return "translate(" + i * (-100) + "," + (height + 50) + ")"; });

        debugger;
        legend.append("rect")
            .attr("x", width - 18)
            .attr("width", 18)
            .attr("height", 18)
            .style("fill", function (d, i) { return colors[i]; })
        .on("mouseover", function (d, i) {
            svg.selectAll("rect.color-" + colors[i].substring(1)).style("stroke", "blue");
        })
        .on("mouseout", function (d, i) {
            svg.selectAll("rect.color-" + colors[i].substring(1)).style("stroke", "white");
        });

        legend.append("text")
              .attr("x", width - 24)
              .attr("y", 9)
              .attr("dy", ".35em")
              .style("text-anchor", "end")
              .text(function (d) { return d; });


        transitionStacked();
        function transitionStacked() {

            y.domain([0, yStackMax]);

            rect.transition()
                .duration(500)
                .delay(function (d, i) { return i * 10; })
                .attr("y", function (d) { return y(d.y0 + d.y); })
                .attr("height", function (d) { return y(d.y0) - y(d.y0 + d.y); })
              .transition()
                .attr("x", function (d) { return xScale(d.x); })
                .attr("width", xScale.rangeBand());

        };

   }

谁能帮我解决这个问题。

【问题讨论】:

  • 您能否将完整代码与您的fData 一起发布以观察图表行为。
  • @Amani 我已经用 fData 更新了问题,请检查
  • 你没有任何问题hover 事件你只是给你的课程错误rect 元素

标签: javascript jquery d3.js charts


【解决方案1】:

您将相同的类:color-9999CC 附加到所有rect 元素,因此一旦您将鼠标悬停在最后一个具有颜色的图例项:#9999CC,所有rect 元素将被选中。

要正确创建所需的类,您可以在创建 layers 对象时为每个元素添加相应的颜色信息。

我添加了一个 color 属性,其值为对应的 headers 项目的颜色:

var layers = d3.layout.stack()(
     headers.map(function (count) {
            return fData.map(function (d,i) {
               return { x: d.orders, y: +d[count] , color:  colorScale(count)}; 
                                                   /*color = current headers item color */

            }); 
     }));

然后,在创建 rect 项目时,您可以通过访问其颜色属性为每个元素添加一个类,如下所示:

var rect = layer.selectAll("rect")
            .data(function (d) { return d; })
            .....
            .attr("class", function (d) {
                    return "rect bordered " + "color-" +d.color.substring(1);
            });

完整代码:

var margin = {top:10, right: 10, bottom: 80, left: 50},
    width =960,
    height=650;
var svg = d3.select("body")
  .append("svg")
  .attr("width", width + margin.left + margin.right)
  .attr("height", height + margin.top + margin.bottom)
  .append("g")
  .attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var fData = 

[{"orders":"A","Total_Orders":76,"A_Lines":123,"B_Lines":0,"C_Lines":0,"D_Lines":0,"Total_Lines":123,"Total_Units":3267},
{"orders":"B","Total_Orders":68,"A_Lines":0,"B_Lines":107,"C_Lines":0,"D_Lines":0,"Total_Lines":107,"Total_Units":3115},
{"orders":"C","Total_Orders":81,"A_Lines":0,"B_Lines":0,"C_Lines":123,"D_Lines":0,"Total_Lines":123,"Total_Units":3690},
{"orders":"D","Total_Orders":113,"A_Lines":0,"B_Lines":0,"C_Lines":0,"D_Lines":203,"Total_Lines":203,"Total_Units":7863},
{"orders":"AB","Total_Orders":62,"A_Lines":70,"B_Lines":76,"C_Lines":0,"D_Lines":0,"Total_Lines":146,"Total_Units":1739},
{"orders":"AC","Total_Orders":64,"A_Lines":77,"B_Lines":0,"C_Lines":79,"D_Lines":0,"Total_Lines":156,"Total_Units":2027},
{"orders":"AD","Total_Orders":100,"A_Lines":127,"B_Lines":0,"C_Lines":0,"D_Lines":144,"Total_Lines":271,"Total_Units":6467},
{"orders":"BC","Total_Orders":64,"A_Lines":0,"B_Lines":80,"C_Lines":84,"D_Lines":0,"Total_Lines":164,"Total_Units":1845},
{"orders":"BD","Total_Orders":91,"A_Lines":0,"B_Lines":108,"C_Lines":0,"D_Lines":135,"Total_Lines":243,"Total_Units":4061},
{"orders":"CD","Total_Orders":111,"A_Lines":0,"B_Lines":0,"C_Lines":132,"D_Lines":147,"Total_Lines":279,"Total_Units":5011},
{"orders":"ABC","Total_Orders":45,"A_Lines":58,"B_Lines":63,"C_Lines":55,"D_Lines":0,"Total_Lines":176,"Total_Units":1245},
{"orders":"ABD","Total_Orders":69,"A_Lines":105,"B_Lines":87,"C_Lines":0,"D_Lines":116,"Total_Lines":308,"Total_Units":4538},
{"orders":"ACD","Total_Orders":66,"A_Lines":91,"B_Lines":0,"C_Lines":88,"D_Lines":132,"Total_Lines":311,"Total_Units":4446},
{"orders":"BCD","Total_Orders":68,"A_Lines":0,"B_Lines":84,"C_Lines":95,"D_Lines":111,"Total_Lines":290,"Total_Units":4187},
{"orders":"ABCD","Total_Orders":56,"A_Lines":96,"B_Lines":90,"C_Lines":93,"D_Lines":143,"Total_Lines":422,"Total_Units":6331}] 

var headers = ["A_Lines", "B_Lines", "C_Lines", "D_Lines"];
         var colors = ["#9999CC", "#F7A35C", "#99CC99", "#CCCC99"];
          var colorScale = d3.scale.ordinal()
                             .domain(headers)
                             .range(colors);
        var layers = d3.layout.stack()(
           headers.map(function (count) {
            return fData.map(function (d,i) {
               return { x: d.orders, y: +d[count] , color:  colorScale(count)};
                
            }); 
        }));
        //StackedBar Rectangle Max

        var yStackMax = d3.max(layers, function (layer) { return d3.max(layer, function (d) { return d.y0 + d.y; }); });
        // Set x, y and colors
        var xScale = d3.scale.ordinal()
     .domain(layers[0].map(function (d) { return d.x; }))
     .rangeRoundBands([25, width], .08);
       
        var y = d3.scale.linear()
            .domain([0, yStackMax])
            .range([height, 0]);
       
 
        // Define and draw axes
        var xAxis = d3.svg.axis()
                    .scale(xScale)
                    .tickSize(1)
                    .tickPadding(6)
                    .orient("bottom");

        var yAxis = d3.svg.axis()
                    .scale(y)
                    .orient("left")
                    .tickFormat(d3.format(".2s"))



        var layer = svg.selectAll(".layer")
            .data(layers)
            .enter().append("g")
            .attr("class", "layer")
            .style("fill", function (d, i) { return colorScale(i); });
            

        var rect = layer.selectAll("rect")
            .data(function (d) { return d; })
            .enter().append("rect")
            .attr("x", function (d) { return xScale(d.x); })
            .attr("y", height)
            .attr("width", xScale.rangeBand())
            .attr("height", 0)
            .attr("class", function (d,i) {
                    return "rect bordered " + "color-" +d.color.substring(1);
            });
           
         
            
        layer.selectAll("text.rect")
            .data(function (layer) { return layer; })
            .enter().append("text")
            .attr("text-anchor", "middle")
            .attr("x", function (d) { return xScale(d.x) + xScale.rangeBand() / 2; })
            .attr("y", function (d) { return y(d.y + d.y0) - 3; })
            .text(function (d) { return d.y + d.y0; })
            .style("fill", "4682b4");

        //********** AXES ************

        svg.append("g")
             .attr("class", "x axis")
             .attr("transform", "translate(0," + height + ")")
             .call(xAxis)
             .selectAll("text").style("text-anchor", "end")
                 .attr("dx", "-.8em")
                 .attr("dy", ".15em")
                 .attr("transform", function (d) {
                     return "rotate(-45)"
                 });

        svg.attr("class", "x axis")
           .append("text")
           .attr("text-anchor", "end")  // this makes it easy to centre the text as the transform is applied to the anchor
           .attr("transform", "translate(" + (width / 2) + "," + (height + 60) + ")")  // centre below axis
           .text("Order Velocity Group");


        svg.append("g")
            .attr("class", "y axis")
            .attr("transform", "translate(20,0)")
            .call(yAxis)
          .append("text")
            .attr("transform", "rotate(-90)")
            .attr({ "x": -75, "y": -70 })
            .attr("dy", ".75em")
            .style("text-anchor", "end")
            .text("No. Of Lines");

        //********** LEGEND ************
        var legend = svg.selectAll(".legend")
                    .data(headers)
                    .enter().append("g")
                    .attr("class", "legend")
                    .attr("transform", function (d, i) { return "translate(" +  (headers.length-(i+1))*-100 + "," + (height + 50) + ")"; });
        
        legend.append("rect")
            .attr("x", width - 18)
            .attr("width", 18)
            .attr("height", 18)
            .style("fill", function (d, i) { return colors[i]; })
        .on("mouseover", function (d, i) {
        svg.selectAll("rect.color-" + colors[i].substring(1)).style("stroke", "blue");
        })
        .on("mouseout", function (d, i) {
            svg.selectAll("rect.color-" + colors[i].substring(1)).style("stroke", "white");
        });

        legend.append("text")
              .attr("x", width - 24)
              .attr("y", 9)
              .attr("dy", ".35em")
              .style("text-anchor", "end")
              .text(function (d) { return d; });


        transitionStacked();
        function transitionStacked() {

            y.domain([0, yStackMax]);

            rect.transition()
                .duration(500)
                .delay(function (d, i) { return i * 10; })
                .attr("y", function (d) { return y(d.y0 + d.y); })
                .attr("height", function (d) { return y(d.y0) - y(d.y0 + d.y); })
              .transition()
                .attr("x", function (d) { return xScale(d.x); })
                .attr("width", xScale.rangeBand());

        };
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.3.0/d3.min.js"></script>
<body></body>

【讨论】:

  • 感谢@Amani 的快速回复。在这里为条形图和图例分配颜色是错误的。对于“A”矩形颜色显示在“D”图例中。
  • 你好,有什么问题吗?为了更好的观点,我创建了一个小提琴jsfiddle.net/wc41c9wu你能指出我的错误行为吗?
  • 在传说中我保留了 headers.reverse() 来获取 ABCD 顺序,那么如何以相反的顺序更改放置颜色
  • 请看矩形的图例颜色和对应的Hightlight
  • 您可以创建您的图例,而无需像这样反转您的数据:var legend = svg.selectAll(".legend") .data(headers) .enter().append("g") .attr("class", "legend") .attr("transform", function (d, i) { return "translate(" + (headers.length-(i+1))*-100 + "," + (height + 50) + ")"; }); 查看更新的答案
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-06-13
  • 2019-04-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多