代码之家  ›  专栏  ›  技术社区  ›  Ilan Aizelman WS

从json文件构造bar的工具提示值

  •  0
  • Ilan Aizelman WS  · 技术社区  · 6 年前

    我正在努力使工具提示起作用。这是页面的外观[见下面的图片1],我试图将它的y值赋给每个栏。y值存储在 resumeperday.json [见下文]每天都有“时间”和“y”属性。time属性是日期,y是当天的订单数量。那个 resumeperday.json 文件存储为 dataset 变量输入 index.html 文件。我试图解析它的y值,它是所有三个不同顺序的总和(每个日期有三个不同的值),并在鼠标悬停时显示在工具栏上。当我使用这行代码时

      .html(function(d) {
            return "<strong>Number of orders:</strong> <span style='color:red'>" + d3.max(dataset, function(d) {
                            return d3.max(d, function(d) {
                                return d.y0 + d.y;
                            });
                        }) + "</span>";
            })
    

    问题: 它只显示 123 对于每个栏(这是订单的最大值),我试图建立一个函数,它将根据被悬停的特定栏返回值。

    下面是index.html代码:

    <!DOCTYPE html>
    <html lang="en">
        <head>
            <meta charset="utf-8">
            <title>Pizza orders</title>
            <script type="text/javascript" src="http://code.jquery.com/jquery-latest.min.js"></script>
            <script type="text/javascript" src="http://d3js.org/d3.v3.min.js"></script>
            <script src="//netdna.bootstrapcdn.com/bootstrap/3.1.1/js/bootstrap.min.js"></script>
            <script src="http://labratrevenge.com/d3-tip/javascripts/d3.tip.v0.6.3.js"></script>
            <link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css">
            <style>
            .axis path,
    .axis line {
        fill: none;
        stroke: black;
        shape-rendering: crispEdges;
    }
    
    .axis text {
        font-family: sans-serif;
        font-size: 11px;
    }
    
    .dot {
      stroke: #000;
    }
    
    
    .legend {
                    padding: 5px;
                    font: 10px sans-serif;
                    background: yellow;
                    box-shadow: 2px 2px 1px #888;
                }
    .d3-tip {
      line-height: 1;
      font-weight: bold;
      padding: 12px;
      background: rgba(0, 0, 0, 0.8);
      color: #fff;
      border-radius: 2px;
    }
    
    /* Creates a small triangle extender for the tooltip */
    .d3-tip:after {
      box-sizing: border-box;
      display: inline;
      font-size: 10px;
      width: 100%;
      line-height: 1;
      color: rgba(0, 0, 0, 0.8);
      content: "\25BC";
      position: absolute;
      text-align: center;
    }
    
    /* Style northward tooltips differently */
    .d3-tip.n:after {
      margin: -1px 0 0 0;
      top: 100%;
      left: 0;
    }-align: center;
    }
            </style>
        </head>
        <body>
            <div>
                <div class="btn-group pull-right">
                    <button type="button" class="btn btn-primary dropdown-toggle" data-toggle="dropdown">
                             Pizza orders per hour <span class="caret"></span>
                    </button>
                    <ul class="dropdown-menu" role="menu">
                        <li><a class="m" value="2018-07-15" href="#">2018-07-15</a></li>
                        <li><a class="m" value="2018-07-16" href="#">2018-07-16</a></li>
                        <li><a class="m" value="2018-07-17" href="#">2018-07-17</a></li>
                        <li><a class="m" value="2018-07-18" href="#">2018-07-18</a></li>
                        <li><a class="m" value="2018-07-19" href="#">2018-07-19</a></li>
                        <li><a class="m" value="2018-07-20" href="#">2018-07-20</a></li>
                        <li><a class="m" value="2018-07-21" href="#">2018-07-21</a></li>
                    </ul>
                </div>
    
            <div id="mbars">
            </div>
            </div>
            <script type="text/javascript">
            var w = 700;                        //width
            var h = 600;                        //height
            var padding = {top: 40, right: 40, bottom: 40, left:25};
            var dataset;
            var tip = d3.tip()
            .attr('class', 'd3-tip')
            .offset([-10, 0])
            .html(function(d) {
            return "<strong>Number of orders:</strong> <span style='color:red'>" + d3.min(dataset, function(d) {
                            return d3.min(d, function(d) {
                                return d.y0 + d.y;
                            });
                        }) + "</span>";
            })
            //Set up stack method
            var stack = d3.layout.stack();
    
            d3.json("resumeperday.json",function(json){
                dataset = json;
    
                //Data, stacked
                stack(dataset);
    
                var color_hash = {
                        0 : ["50-70₪","#0000FF"],
                        1 : ["70.00-120₪","#FF0000"],
                        2 : ["120+₪","#04B404"]
    
                };
    
    
                //Set up scales
                var xScale = d3.time.scale()
                    .domain([new Date(dataset[0][0].time),d3.time.day.offset(new Date(dataset[0][dataset[0].length-1].time),2)])
                    .rangeRound([0, w-padding.left-padding.right]);
    
                var yScale = d3.scale.linear()
                    .domain([0,             
                        d3.max(dataset, function(d) {
                            return d3.max(d, function(d) {
                                return d.y0 + d.y;
                            });
                        })
                    ])
                    .range([h-padding.bottom-padding.top,0]);
    
                var xAxis = d3.svg.axis()
                               .scale(xScale)
                               .orient("bottom")
                               .ticks(d3.time.days,1);
    
                var yAxis = d3.svg.axis()
                               .scale(yScale)
                               .orient("left")
                               .ticks(10);
    
    
    
                //Easy colors accessible via a 10-step ordinal scale
                var colors = d3.scale.category10();
    
                //Create SVG element
                var svg = d3.select("#mbars")
                            .append("svg")
                            .attr("width", w)
                            .attr("height", h);
    
                svg.call(tip);
    
    
                // Add a group for each row of data
                var groups = svg.selectAll("g")
                    .data(dataset)
                    .enter()
                    .append("g")
                    .attr("class","rgroups")
                    .attr("transform","translate("+ (padding.left) + "," + (h - padding.bottom) +")")
                    .style("fill", function(d, i) {
                        return color_hash[dataset.indexOf(d)][1];
                    })
                    .on('mouseover', tip.show)
                    .on('mouseout', tip.hide);
    
                // Add a rect for each data value
                var rects = groups.selectAll("rect")
                    .data(function(d) { return d; })
                    .enter()
                    .append("rect")
                    .attr("width", 2)
                    .style("fill-opacity",1e-6);
    
    
                rects.transition()
                     .duration(function(d,i){
                         return 500 * i;
                     })
                     .ease("linear")
                    .attr("x", function(d) {
                        return xScale(new Date(d.time));
                    })
                    .attr("y", function(d) {
                        return -(- yScale(d.y0) - yScale(d.y) + (h - padding.top - padding.bottom)*2);
                    })
                    .attr("height", function(d) {
                        return -yScale(d.y) + (h - padding.top - padding.bottom);
                    })
                    .attr("width", 15)
                    .style("fill-opacity",1);
    
                    svg.append("g")
                        .attr("class","x axis")
                        .attr("transform","translate(40," + (h - padding.bottom) + ")")
                        .call(xAxis);
    
    
                    svg.append("g")
                        .attr("class","y axis")
                        .attr("transform","translate(" + padding.left + "," + padding.top + ")")
                        .call(yAxis);
    
                    // adding legend
    
                    var legend = svg.append("g")
                                    .attr("class","legend")
                                    .attr("x", w - padding.right - 65)
                                    .attr("y", 25)
                                    .attr("height", 100)
                                    .attr("width",100);
    
                    legend.selectAll("g").data(dataset)
                          .enter()
                          .append('g')
                          .each(function(d,i){
                            var g = d3.select(this);
                            g.append("rect")
                                .attr("x", w - padding.right - 30)
                                .attr("y", i*25 + 10)
                                .attr("width", 10)
                                .attr("height",10)
                                .style("fill",color_hash[String(i)][1]);
    
                            g.append("text")
                             .attr("x", w - padding.right - 15)
                             .attr("y", i*25 + 20)
                             .attr("height",30)
                             .attr("width",100)
                             .style("fill",color_hash[String(i)][1])
                             .text(color_hash[String(i)][0]);
                          });
    
                    svg.append("text")
                    .attr("transform","translate(5,20) rotate(0)")
                    .attr("font-weight","bold")
                    .text("Pizza Orders");
    
                svg.append("text")
                   .attr("class","xtext")
                   .attr("x",w/2 - padding.left)
                   .attr("y",h - 5)
                   .attr("text-anchor","middle")
                   .attr("font-weight","bold")
                   .text("Days");
    
                svg.append("text")
                .attr("class","title")
                .attr("x", (w / 2))             
                .attr("y", 20)
                .attr("text-anchor", "middle")
                .attr("font-weight","bold")         
                .style("font-size", "16px") 
                .style("text-decoration", "underline")  
                .text("Number of Pizza Orders per day");
    
                //On click, update with new data            
                d3.selectAll(".m")
                    .on("click", function() {
                        var date = this.getAttribute("value");
    
                        var str;
                        if(date == "2018-07-15"){
                            str = "15.json";
                        }else if(date == "2018-07-16"){
                            str = "16.json";
                        }else if(date == "2018-07-17"){
                            str = "17.json";
                        }else if(date == "2018-07-18"){
                            str = "18.json";
                        }else if(date == "2018-07-19"){
                            str = "19.json";
                        }
                        else if(date == "2018-07-20"){
                            str = "20.json";
                        }else{
                            str = "21.json";
                        }
    
                        d3.json(str,function(json){
    
                            dataset = json;
                            stack(dataset);
    
                            console.log(dataset);
    
                            xScale.domain([new Date(0, 0, 0,dataset[0][0].time,0, 0, 0),new Date(0, 0, 0,dataset[0][dataset[0].length-1].time,0, 0, 0)])
                            .rangeRound([0, w-padding.left-padding.right]);
    
                            yScale.domain([0,               
                                            d3.max(dataset, function(d) {
                                                return d3.max(d, function(d) {
                                                    return d.y0 + d.y;
                                                });
                                            })
                                        ])
                                        .range([h-padding.bottom-padding.top,0]);
    
                            xAxis.scale(xScale)
                                 .ticks(d3.time.hour,1)
                                 .tickFormat(d3.time.format("%H"));
    
                            yAxis.scale(yScale)
                                 .orient("left")
                                 .ticks(10);
    
                             groups = svg.selectAll(".rgroups")
                                .data(dataset);
    
                                groups.enter().append("g")
                                .attr("class","rgroups")
                                .attr("transform","translate("+ padding.left + "," + (h - padding.bottom) +")")
                                .style("fill",function(d,i){
                                    return color(i);
                                });
    
    
                                rect = groups.selectAll("rect")
                                .data(function(d){return d;});
    
                                rect.enter()
                                  .append("rect")
                                  .attr("x",w)
                                  .attr("width",1)
                                  .style("fill-opacity",1e-6);
    
                            rect.transition()
                                .duration(1000)
                                .ease("linear")
                                .attr("x",function(d){
                                    return xScale(new Date(0, 0, 0,d.time,0, 0, 0));
                                })
                                .attr("y",function(d){
                                    return -(- yScale(d.y0) - yScale(d.y) + (h - padding.top - padding.bottom)*2);
                                })
                                .attr("height",function(d){
                                    return -yScale(d.y) + (h - padding.top - padding.bottom);
                                })
                                .attr("width",15)
                                .style("fill-opacity",1);
    
                            rect.exit()
                               .transition()
                               .duration(1000)
                               .ease("circle")
                               .attr("x",w)
                               .remove();
    
                            groups.exit()
                               .transition()
                               .duration(1000)
                               .ease("circle")
                               .attr("x",w)
                               .remove();
    
    
                            svg.select(".x.axis")
                               .transition()
                               .duration(1000)
                               .ease("circle")
                               .call(xAxis);
    
                            svg.select(".y.axis")
                               .transition()
                               .duration(1000)
                               .ease("circle")
                               .call(yAxis);
    
                            svg.select(".xtext")
                               .text("Hours")
                               .attr("font-weight","bold");
    
                            svg.select(".title")
                            .text("Number of Pizza Orders per hour on " + date)
                            .attr("font-weight","bold");
                        });         
                    });
    
    
            });
    
            </script>
        </body>
    </html>
    

    resumeperday.json 文件:

    [
        [
            {
                "time": "2018-07-15",
                "y": 27
            },
            {
                "time": "2018-07-16",
                "y": 23
            },
            {
                "time": "2018-07-17",
                "y": 28
            },
            {
                "time": "2018-07-18",
                "y": 20
            },
            {
                "time": "2018-07-19",
                "y": 22
            },
            {
                "time": "2018-07-20",
                "y": 27
            },
            {
                "time": "2018-07-21",
                "y": 21
            }
        ],
        [
            {
                "time": "2018-07-15",
                "y": 29
            },
            {
                "time": "2018-07-16",
                "y": 26
            },
            {
                "time": "2018-07-17",
                "y": 31
            },
            {
                "time": "2018-07-18",
                "y": 27
            },
            {
                "time": "2018-07-19",
                "y": 31
            },
            {
                "time": "2018-07-20",
                "y": 65
            },
            {
                "time": "2018-07-21",
                "y": 37
            }
        ],
        [
            {
                "time": "2018-07-15",
                "y": 17
            },
            {
                "time": "2018-07-16",
                "y": 16
            },
            {
                "time": "2018-07-17",
                "y": 16
            },
            {
                "time": "2018-07-18",
                "y": 15
            },
            {
                "time": "2018-07-19",
                "y": 22
            },
            {
                "time": "2018-07-20",
                "y": 31
            },
            {
                "time": "2018-07-21",
                "y": 23
            }
        ]
    ]
    

    [照片1]只有特定的栏“123”才是正确的。

    enter image description here

    1 回复  |  直到 6 年前
        1
  •  1
  •   rioV8    6 年前

    问题是你按颜色将矩形分组。 如果将光标悬停在矩形上,将得到属于该颜色组的基准。你看不到你在上面徘徊的酒吧。

    按类而不是按元素类型选择组。

    var groups = svg.selectAll(".rgroups")
                    .data(dataset)
                    .enter()
                    .append("g")
                    .attr("class","rgroups")
                    .attr("transform","translate("+ (padding.left) + "," + (h - padding.bottom) +")")
                    .style("fill", function(d, i) {
                        return color_hash[dataset.indexOf(d)][1];
                    })
                    .on('mouseover', tip.show)
                    .on('mouseout', tip.hide);
    

    您必须转换数据集,这样就有了一个表示特定条的所有数据的对象/数组。 d3.nest 可能会有帮助。

    然后构造一个 g 按条添加矩形 . 然后在工具提示中,您将获得属于此栏的数据。

    仔细看看 .d3-tip.n:after . 它有一个错误。