Выделите соответствующий слой в столбчатой диаграмме с накоплением при наведении курсора мыши на легенду в d3

#javascript #jquery #d3.js #charts

#javascript #jquery #d3.js #Диаграммы

Вопрос:

Я создал столбчатую диаграмму с наложением, теперь я расширяю функцию диаграммы, так как при наведении курсора мыши на легенду должны выделяться соответствующие столбцы.

Проблема, с которой я сталкиваюсь, заключается в том, что событие наведения курсора мыши работает только с последней легендой, но выделяет каждый прямоугольный слой на диаграмме.

Проблема, показанная на рисунке ниже.введите описание изображения здесьЭто изображение появляется при наведении курсора мыши на 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());

        };

   }
  

Может ли кто-нибудь помочь мне преодолеть эту проблему.

Комментарии:

1. не могли бы вы опубликовать полный код с вашим fData , чтобы наблюдать за поведением диаграммы.

2. @Amani Я обновил вопрос с помощью FData, пожалуйста, проверьте

3. с вами ничего hover не случилось, если вы просто присваиваете неправильный класс вашим rect элементам

Ответ №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>  

Комментарии:

1. Спасибо @Amani за быстрый ответ. Здесь присвоение цветов столбцам и легенде неверно. Для прямоугольника «A» цвет отображается в легенде «D».

2. Привет, что именно не так? для лучшего представления я создал скрипку jsfiddle.net/wc41c9wu не могли бы вы указать мне на неправильное поведение?

3. В легенде я сохранил headers.reverse(), чтобы получить порядок ABCD, так как изменить цвета размещения в обратном порядке

4. Пожалуйста, посмотрите на цвет легенды и соответствующий верхний свет прямоугольника

5. вы можете создать свою легенду, полностью изменив свои данные следующим образом: 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) ")"; }); См. Обновленный ответ