简体   繁体   English

d3.js-多系列折线图工具提示问题

[英]d3.js - Multi series line chart tool tip issue

I am new to d3.js got the following code from stack overflow. 我是d3.js的新手,它从堆栈溢出中获得了以下代码。 I had customized it according to my needs. 我已经根据需要定制了它。 But when adding tool tip it is not moving according to the mouse movement and also only date is showing on top of y axis. 但是,当添加工具提示时,它不会根据鼠标的移动而移动,并且在y轴的顶部仅显示日期。 I need to display tool tip in the order Date: date -newline- OP: some value -newline- IP: some value -newline- Pharmacy: some value -newline- Total: OP+IP+Pharmacy where mouse is hover on the line. 我需要按顺序显示工具提示日期:date -newline- OP:一些值-newline- IP:一些值-newline- Pharmacy:一些值-newline- Total:OP + IP + Pharmacy,鼠标悬停在行上。

TSV file and code is as follows. TSV文件和代码如下。 Thanks in advance. 提前致谢。

html file html文件

</!DOCTYPE html>
<html>
<head>

<style>

body {
  font: 10px sans-serif;
}

.axis path,
.axis line {
  fill: none;
  stroke: #000;
  shape-rendering: crispEdges;
}


.line {
  fill: none;
  stroke: steelblue;
  stroke-width: 1.5px;
}

</style>
 <script type="text/javascript" src="assets/js/plugins/visualization/d3/d3.min.js"></script>
</head>
<body>
<div id="revenueStati"></div>
<script>
linchart();
function linchart(){
var margin = {top: 20, right: 80, bottom: 30, left: 50},
    width = 960 - margin.left - margin.right,
    height = 500 - margin.top - margin.bottom;

var parseDate = d3.time.format("%Y%m%d").parse;
var formatDate = d3.time.format("%d-%b")
 var bisectDate = d3.bisector(function(d) { return d.date; }).left
var x = d3.time.scale()
    .range([0, width]);

var y = d3.scale.linear()
    .range([height-10, 0]);

var color = d3.scale.category10();

var xAxis = d3.svg.axis()
    .scale(x)
    .orient("bottom").ticks(7);

var yAxis = d3.svg.axis()
    .scale(y)
    .orient("left");

var line = d3.svg.line()
    .interpolate("basis")
    .x(function(d) { return x(d.date); })
    .y(function(d) { return y(d.temperature); });

var svg = d3.select("#revenueStati").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 + ")");





d3.tsv("data.tsv", function(error, data) {
  if (error) throw error;

  color.domain(d3.keys(data[0]).filter(function(key) { return key !== "date"; }));

  data.forEach(function(d) {
    d.date = parseDate(d.date);
  });

  var cities = color.domain().map(function(name) {
    return {
      name: name,
      values: data.map(function(d) {
        return {date: d.date, temperature: +d[name]};
      })
    };
  });

  x.domain(d3.extent(data, function(d) { return d.date; }));

  y.domain([
    d3.min(cities, function(c) { return d3.min(c.values, function(v) { return v.temperature; }); }),
    d3.max(cities, function(c) { return d3.max(c.values, function(v) { return v.temperature; }); })
  ]);

  svg.append("g")
      .attr("class", "x axis")
      .attr("transform", "translate(0," + height + ")")
      .call(xAxis);

  svg.append("g")
      .attr("class", "y axis")
      .call(yAxis)
    .append("text")
      .attr("transform", "rotate(-90)")
      .attr("y", 6)
      .attr("dy", ".71em")
      .style("text-anchor", "end");

  var city = svg.selectAll(".city")
      .data(cities)
    .enter().append("g")
      .attr("class", "city");

  city.append("path")
      .attr("class", "line")
      .attr("d", function(d) { return line(d.values); })
      .style("stroke", function(d) { return color(d.name); });

  city.append("text")
      .datum(function(d) { return {name: d.name, value: d.values[d.values.length - 1]}; })
      .attr("transform", function(d) { return "translate(" + x(d.value.date) + "," + y(d.value.temperature) + ")"; })
      .attr("x", 3)
      .attr("dy", ".35em")
      .text(function(d) { return d.name; });

      //// - tooltip


city = svg.append("g") 
    .style("display", "none");
      // append the x line
    city.append("line")
        .attr("class", "x")
        .style("stroke", "blue")
        .style("stroke-dasharray", "3,3")
        .style("opacity", 0.5)
        .attr("y1", 0)
        .attr("y2", height);

    // append the y line
    city.append("line")
        .attr("class", "y")
        .style("stroke", "blue")
        .style("stroke-dasharray", "3,3")
        .style("opacity", 0.5)
        .attr("x1", width)
        .attr("x2", width);

    // append the circle at the intersection
    city.append("circle")
        .attr("class", "y")
        .style("fill", "none")
        .style("stroke", "blue")
        .attr("r", 4);

    // place the value at the intersection
    city.append("text")
        .attr("class", "y1")
        .style("stroke", "white")
        .style("stroke-width", "3.5px")
        .style("opacity", 0.8)
        .attr("dx", 8)
        .attr("dy", "-.3em");
    city.append("text")
        .attr("class", "y2")
        .attr("dx", 8)
        .attr("dy", "-.3em");

    // place the date at the intersection
    city.append("text")
        .attr("class", "y3")
        .style("stroke", "white")
        .style("stroke-width", "3.5px")
        .style("opacity", 0.8)
        .attr("dx", 8)
        .attr("dy", "1em");
    city.append("text")
        .attr("class", "y4")
        .attr("dx", 8)
        .attr("dy", "1em");

    // append the rectangle to capture mouse
    svg.append("rect")
        .attr("width", width)
        .attr("height", height)
        .style("fill", "none")
        .style("pointer-events", "all")
        .on("mouseover", function() { city.style("display", null); })
        .on("mouseout", function() { city.style("display", "none"); })
        .on("mousemove", mousemove);

    function mousemove() {
    var x0 = x.invert(d3.mouse(this)[0]),
        i = bisectDate(data, x0, 1),
        d0 = data[i - 1],
        d1 = data[i],
        d = x0 - d0.date > d1.date - x0 ? d1 : d0;

    city.select("circle.y")
        .attr("transform",
              "translate(" + x(d.date) + "," +
                             y(d.close) + ")");

    city.select("text.y1")
        .attr("transform",
              "translate(" + x(d.date) + "," +
                             y(d.close) + ")")
        .text(d.close);

    city.select("text.y2")
        .attr("transform",
              "translate(" + x(d.date) + "," +
                             y(d.close) + ")")
        .text(d.close);

    city.select("text.y3")
        .attr("transform",
              "translate(" + x(d.date) + "," +
                             y(d.close) + ")")
        .text(formatDate(d.date));

    city.select("text.y4")
        .attr("transform",
              "translate(" + x(d.date) + "," +
                             y(d.close) + ")")
        .text(formatDate(d.date));

    city.select(".x")
        .attr("transform",
              "translate(" + x(d.date) + "," +
                             y(d.close) + ")")
                   .attr("y2", height - y(d.close));

    city.select(".y")
        .attr("transform",
              "translate(" + width * -1 + "," +
                             y(d.close) + ")")
                   .attr("x2", width + width);
  }

});
}

</script>
</body>

</html>

data.tsv file data.tsv文件

date    OP  IP  Pharmacy
20160406    46905.00    10360.00    52558.00
20160407    45415.00    10910.00    46665.00
20160408    69770.00    10935.00    46377.00
20160409    58455.00    29900.00    37352.00
20160410    10345.00    7200.00 22971.00
20160411    48680.00    14535.00    46482.00
20160412    42452.00    16270.00    34859.00

演示图

You code is take from examples with One data serie and you have multiple series: 您的代码摘自具有一个数据系列的示例,并且您有多个系列:

The important start here: 重要的开始在这里:

var x0 = x.invert(d3.mouse(this)[0]),
    i = bisectDate(data, x0, 1),
    d0 = data[i - 1],
    d1 = data[i],
    d = x0 - d0.date > d1.date - x0 ? d1 : d0;

city.select("circle.y")
    .attr("transform",
          "translate(" + x(d.date) + "," +  // based on date
                         y(d.close) + ")"); // you need find y value 
                                            // d.close is not defined

You have 3 serie. 您有3个意甲。 You could take the max value at some date and draw the circle there: 您可以在某个日期取最大值,并在那里画一个圆圈:

var ymax = d3.max([+d["OP"],+d["IP"],+d["Pharmacy"]])
var xm = x(d.date);
var ym = y(ymax);

city.select("circle.y")
    .attr("transform",
          "translate(" + xm + "," +
                         ym + ")");

Or, draw three circles, one for each series: 或者,绘制三个圆圈,每个系列一个:

city.select("circle.y")
    .attr("transform",
          "translate(" + xm + "," +
                         y(+d["OP"]) + ")");

city.select("circle.y")
    .attr("transform",
          "translate(" + xm + "," +
                         y(+d["IP"]) + ")");

city.select("circle.y")
    .attr("transform",
          "translate(" + xm + "," +
                         y(+d["Pharmacy"]) + ")");

Now you know how to calulate (x,y) you can do the horizontal & vertical dashed lines with labels. 现在您知道如何计算(x,y)了,可以使用标签制作水平和垂直虚线。

Here's s psudoworking code . 这是伪操作代码 I've let you complete it as homework :) 我已让您完成作业:)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM