D3图没有行

时间:2018-07-11 16:46:17

标签: d3.js

我正在尝试将this D3示例从版本4转换为版本5,但是由于某些原因,我无法使线在图表上工作。 我没有错误,并且在移动鼠标时更新了值,但是看不到任何行! 我不明白我是否想念一些东西。代码有什么问题?

此外,我还需要一个函数来从jason文件中获取(字符串)数据并将其转换为数字

var data = [
    {"date": "20111001",  "New York": "63.4",  "San Francisco": "62.7",  "Austin": "72.2"},
    {"date": "20111002",  "New York": "58.0",  "San Francisco": "59.9",  "Austin": "67.7"},
    {"date": "20111002",  "New York": "58.0",  "San Francisco": "59.9",  "Austin": "67.7"},
    {"date": "20111003",  "New York": "53.3",  "San Francisco": "59.1",  "Austin": "69.4"},
    {"date": "20111004",  "New York": "55.7",  "San Francisco": "58.8",  "Austin": "68.0"},
    {"date": "20111005",  "New York": "64.2",  "San Francisco": "58.7",  "Austin": "72.4"},
    {"date": "20111006",  "New York": "58.8",  "San Francisco": "57.0",  "Austin": "77.0"},
    {"date": "20111007",  "New York": "57.9",  "San Francisco": "56.7",  "Austin": "82.3"},
    {"date": "20111008",  "New York": "61.8",  "San Francisco": "56.8",  "Austin": "78.9"},
    {"date": "20111009",  "New York": "69.3",  "San Francisco": "56.7",  "Austin": "68.8"},
    {"date": "20111010",  "New York": "71.2",  "San Francisco": "60.1",  "Austin": "68.7"},
    {"date": "20111011",  "New York": "68.7",  "San Francisco": "61.1",  "Austin": "70.3"},
    {"date": "20111012",  "New York": "61.8",  "San Francisco": "61.5",  "Austin": "75.3"},
    {"date": "20111013",  "New York": "63.0",  "San Francisco": "64.3",  "Austin": "76.6"},
    {"date": "20111014",  "New York": "66.9",  "San Francisco": "67.1",  "Austin": "66.6"},
    {"date": "20111015",  "New York": "61.7",  "San Francisco": "64.6",  "Austin": "68.0"},
    {"date": "20111016",  "New York": "61.8",  "San Francisco": "61.6",  "Austin": "70.6"},
    {"date": "20111017",  "New York": "62.8",  "San Francisco": "61.1",  "Austin": "71.1"},
    {"date": "20111018",  "New York": "60.8",  "San Francisco": "59.2",  "Austin": "70.0"},
    {"date": "20111019",  "New York": "62.1",  "San Francisco": "58.9",  "Austin": "61.6"},
    {"date": "20111020",  "New York": "65.1",  "San Francisco": "57.2",  "Austin": "57.4"},
    {"date": "20111021",  "New York": "55.6",  "San Francisco": "56.4",  "Austin": "64.3"},
    {"date": "20111022",  "New York": "54.4",  "San Francisco": "60.7",  "Austin": "72.4"},
    {"date": "20111023",  "New York": "54.4",  "San Francisco": "65.1",  "Austin": "72.4"},
    {"date": "20111024",  "New York": "54.8",  "San Francisco": "60.9",  "Austin": "72.5"},
    {"date": "20111025",  "New York": "57.9",  "San Francisco": "56.1",  "Austin": "72.7"},
    {"date": "20111026",  "New York": "54.6",  "San Francisco": "54.6",  "Austin": "73.4"},
    {"date": "20111027",  "New York": "54.4",  "San Francisco": "56.1",  "Austin": "70.7"},
    {"date": "20111028",  "New York": "42.5",  "San Francisco": "58.1",  "Austin": "56.8"},
    {"date": "20111029",  "New York": "40.9",  "San Francisco": "57.5",  "Austin": "51.0"},
    {"date": "20111030",  "New York": "38.6",  "San Francisco": "57.7",  "Austin": "54.9"},
    {"date": "20111031",  "New York": "44.2",  "San Francisco": "55.1",  "Austin": "58.8"},
    {"date": "20111101",  "New York": "49.6",  "San Francisco": "57.9",  "Austin": "62.6"},
    {"date": "20111102",  "New York": "47.2",  "San Francisco": "64.6",  "Austin": "71.0"},
    {"date": "20111103",  "New York": "50.1",  "San Francisco": "56.2",  "Austin": "58.4"},
    {"date": "20111104",  "New York": "50.1",  "San Francisco": "50.5",  "Austin": "45.1"},
    {"date": "20111105",  "New York": "43.5",  "San Francisco": "51.3",  "Austin": "52.2"},
    {"date": "20111106",  "New York": "43.8",  "San Francisco": "52.6",  "Austin": "73.0"},
    {"date": "20111107",  "New York": "48.9",  "San Francisco": "51.4",  "Austin": "75.4"},
    {"date": "20111108",  "New York": "55.5",  "San Francisco": "50.6",  "Austin": "72.1"},
    {"date": "20111109",  "New York": "53.7",  "San Francisco": "54.6",  "Austin": "56.6"},
    {"date": "20111110",  "New York": "57.7",  "San Francisco": "55.6",  "Austin": "55.4"},
    {"date": "20111111",  "New York": "48.5",  "San Francisco": "53.9",  "Austin": "46.7"},
    {"date": "20111112",  "New York": "46.8",  "San Francisco": "54.0",  "Austin": "62.0"},
    {"date": "20111113",  "New York": "51.1",  "San Francisco": "53.8",  "Austin": "71.6"},
    {"date": "20111114",  "New York": "56.8",  "San Francisco": "53.5",  "Austin": "75.5"},
    {"date": "20111115",  "New York": "59.7",  "San Francisco": "53.4",  "Austin": "72.1"},
    {"date": "20111116",  "New York": "56.5",  "San Francisco": "52.2",  "Austin": "65.7"},
    {"date": "20111117",  "New York": "49.6",  "San Francisco": "52.7",  "Austin": "56.8"},
    {"date": "20111118",  "New York": "41.5",  "San Francisco": "53.1",  "Austin": "49.9"},
    {"date": "20111119",  "New York": "44.3",  "San Francisco": "49.0",  "Austin": "71.7"},
    {"date": "20111120",  "New York": "54.0",  "San Francisco": "50.4",  "Austin": "77.7"},
    {"date": "20111121",  "New York": "54.1",  "San Francisco": "51.1",  "Austin": "76.4"},
    {"date": "20111122",  "New York": "49.4",  "San Francisco": "52.3",  "Austin": "68.8"},
    {"date": "20111123",  "New York": "50.0",  "San Francisco": "54.6",  "Austin": "57.0"},
    {"date": "20111124",  "New York": "44.0",  "San Francisco": "55.1",  "Austin": "55.5"},
    {"date": "20111125",  "New York": "50.3",  "San Francisco": "51.5",  "Austin": "61.6"},
    {"date": "20111126",  "New York": "52.1",  "San Francisco": "53.6",  "Austin": "64.1"},
    {"date": "20111127",  "New York": "49.6",  "San Francisco": "52.3",  "Austin": "51.1"},
    {"date": "20111128",  "New York": "57.2",  "San Francisco": "51.0",  "Austin": "43.0"}
    ];
        var margin = {
            top: 20,
            right: 80,
            bottom: 30,
            left: 50
          },
          width = 900 - margin.left - margin.right,
          height = 500 - margin.top - margin.bottom;
    
        var parseDate = d3.timeFormat("%Y%m%d");
    
        var x = d3.scaleTime()
          .range([0, width]);
    
        var y = d3.scaleLinear()
          .range([height, 0]);
    
        var color = d3.scaleOrdinal(d3.schemeCategory10);
    
        var xAxis = d3.axisBottom()
          .scale(x);
    
        var yAxis = d3.axisLeft()
          .scale(y);
    
        var line = d3.line()
          .curve(d3.curveBasis)
          .x(function(d) {
            return x(d.date);
          })
          .y(function(d) {
            return y(d.temperature);
          });
    
        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 + ")");
    
        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;
            });
          })
        ]);
    
        var legend = svg.selectAll('g')
          .data(cities)
          .enter()
          .append('g')
          .attr('class', 'legend');
    
        legend.append('rect')
          .attr('x', width - 20)
          .attr('y', function(d, i) {
            return i * 20;
          })
          .attr('width', 10)
          .attr('height', 10)
          .style('fill', function(d) {
            return color(d.name);
          });
    
        legend.append('text')
          .attr('x', width - 8)
          .attr('y', function(d, i) {
            return (i * 20) + 9;
          })
          .text(function(d) {
            return d.name;
          });
    
        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")
          .text("Temperature (ºF)");
    
        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;
          });
    
        var mouseG = svg.append("g")
          .attr("class", "mouse-over-effects");
    
        mouseG.append("path") 
          .attr("class", "mouse-line")
          .style("stroke", "black")
          .style("stroke-width", "1px")
          .style("opacity", "0");
          
        var lines = document.getElementsByClassName('line');
    
        var mousePerLine = mouseG.selectAll('.mouse-per-line')
          .data(cities)
          .enter()
          .append("g")
          .attr("class", "mouse-per-line");
    
        mousePerLine.append("circle")
          .attr("r", 7)
          .style("stroke", function(d) {
            return color(d.name);
          })
          .style("fill", "none")
          .style("stroke-width", "1px")
          .style("opacity", "0");
    
        mousePerLine.append("text")
          .attr("transform", "translate(10,3)");
    
        mouseG.append('svg:rect') // append a rect to catch mouse movements on canvas
          .attr('width', width) // can't catch mouse events on a g element
          .attr('height', height)
          .attr('fill', 'none')
          .attr('pointer-events', 'all')
          .on('mouseout', function() { // on mouse out hide line, circles and text
            d3.select(".mouse-line")
              .style("opacity", "0");
            d3.selectAll(".mouse-per-line circle")
              .style("opacity", "0");
            d3.selectAll(".mouse-per-line text")
              .style("opacity", "0");
          })
          .on('mouseover', function() { // on mouse in show line, circles and text
            d3.select(".mouse-line")
              .style("opacity", "1");
            d3.selectAll(".mouse-per-line circle")
              .style("opacity", "1");
            d3.selectAll(".mouse-per-line text")
              .style("opacity", "1");
          })
          .on('mousemove', function() { // mouse moving over canvas
            var mouse = d3.mouse(this);
            d3.select(".mouse-line")
              .attr("d", function() {
                var d = "M" + mouse[0] + "," + height;
                d += " " + mouse[0] + "," + 0;
                return d;
              });
    
            d3.selectAll(".mouse-per-line")
              .attr("transform", function(d, i) {
                console.log(width/mouse[0])
                var xDate = x.invert(mouse[0]),
                    bisect = d3.bisector(function(d) { return d.date; }).right;
                    idx = bisect(d.values, xDate);
                
                var beginning = 0,
                    end = lines[i].getTotalLength(),
                    target = null;
    
                while (true){
                  target = Math.floor((beginning + end) / 2);
                  pos = lines[i].getPointAtLength(target);
                  if ((target === end || target === beginning) && pos.x !== mouse[0]) {
                      break;
                  }
                  if (pos.x > mouse[0])      end = target;
                  else if (pos.x < mouse[0]) beginning = target;
                  else break; //position found
                }
                
                d3.select(this).select('text')
                  .text(y.invert(pos.y).toFixed(2));              
                return "translate(" + mouse[0] + "," + pos.y +")";
              });
          });
body {
          font: 10px sans-serif;
        }
        
        .axis path,
        .axis line {
          fill: none;
          stroke: #000;
          shape-rendering: crispEdges;
        }
        
        .x.axis path {
          display: none;
        }
        
        .line {
          fill: none;
          stroke: steelblue;
          stroke-width: 1.5px;
        }
<script src="https://d3js.org/d3.v5.min.js" charset="utf-8"></script>

1 个答案:

答案 0 :(得分:0)

画出了线条,它们只是异常地向左绘制。

问题在于您正在格式化时间,而不是解析时间:

var date = "20111127";

var formatDate = d3.timeFormat("%Y%m%d");
var parseDate = d3.timeParse("%Y%m%d");

console.log("formatted: " + formatDate(date));
console.log("parsed: " + parseDate(date));
  <script src="https://d3js.org/d3.v5.min.js" charset="utf-8"></script>

碰巧的是,您的日期字符串可能会被解析为时间,并且会被提供为格式输入。这就是为什么没有看到错误的原因。

冒名顶替的原因很有趣。输入字符串自该纪元开始以来被读取为秒,并被格式化为yearmonthday,将其格式化为同一天(给定数字):19691231 (在我的时区中,这就是它为纪元前的原因) )。再次从纪元 开始以秒为单位读取,这一次是按比例。由于每个点都具有相同的时间,所以域的起点和终点是相同的,并且比例尺有些许中断。

更新的代码段:

   var data = [
{"date": "20111001",  "New York": "63.4",  "San Francisco": "62.7",  "Austin": "72.2"},
{"date": "20111002",  "New York": "58.0",  "San Francisco": "59.9",  "Austin": "67.7"},
{"date": "20111002",  "New York": "58.0",  "San Francisco": "59.9",  "Austin": "67.7"},
{"date": "20111003",  "New York": "53.3",  "San Francisco": "59.1",  "Austin": "69.4"},
{"date": "20111004",  "New York": "55.7",  "San Francisco": "58.8",  "Austin": "68.0"},
{"date": "20111005",  "New York": "64.2",  "San Francisco": "58.7",  "Austin": "72.4"},
{"date": "20111006",  "New York": "58.8",  "San Francisco": "57.0",  "Austin": "77.0"},
{"date": "20111007",  "New York": "57.9",  "San Francisco": "56.7",  "Austin": "82.3"},
{"date": "20111008",  "New York": "61.8",  "San Francisco": "56.8",  "Austin": "78.9"},
{"date": "20111009",  "New York": "69.3",  "San Francisco": "56.7",  "Austin": "68.8"},
{"date": "20111010",  "New York": "71.2",  "San Francisco": "60.1",  "Austin": "68.7"},
{"date": "20111011",  "New York": "68.7",  "San Francisco": "61.1",  "Austin": "70.3"},
{"date": "20111012",  "New York": "61.8",  "San Francisco": "61.5",  "Austin": "75.3"},
{"date": "20111013",  "New York": "63.0",  "San Francisco": "64.3",  "Austin": "76.6"},
{"date": "20111014",  "New York": "66.9",  "San Francisco": "67.1",  "Austin": "66.6"},
{"date": "20111015",  "New York": "61.7",  "San Francisco": "64.6",  "Austin": "68.0"},
{"date": "20111016",  "New York": "61.8",  "San Francisco": "61.6",  "Austin": "70.6"},
{"date": "20111017",  "New York": "62.8",  "San Francisco": "61.1",  "Austin": "71.1"},
{"date": "20111018",  "New York": "60.8",  "San Francisco": "59.2",  "Austin": "70.0"},
{"date": "20111019",  "New York": "62.1",  "San Francisco": "58.9",  "Austin": "61.6"},
{"date": "20111020",  "New York": "65.1",  "San Francisco": "57.2",  "Austin": "57.4"},
{"date": "20111021",  "New York": "55.6",  "San Francisco": "56.4",  "Austin": "64.3"},
{"date": "20111022",  "New York": "54.4",  "San Francisco": "60.7",  "Austin": "72.4"},
{"date": "20111023",  "New York": "54.4",  "San Francisco": "65.1",  "Austin": "72.4"},
{"date": "20111024",  "New York": "54.8",  "San Francisco": "60.9",  "Austin": "72.5"},
{"date": "20111025",  "New York": "57.9",  "San Francisco": "56.1",  "Austin": "72.7"},
{"date": "20111026",  "New York": "54.6",  "San Francisco": "54.6",  "Austin": "73.4"},
{"date": "20111027",  "New York": "54.4",  "San Francisco": "56.1",  "Austin": "70.7"},
{"date": "20111028",  "New York": "42.5",  "San Francisco": "58.1",  "Austin": "56.8"},
{"date": "20111029",  "New York": "40.9",  "San Francisco": "57.5",  "Austin": "51.0"},
{"date": "20111030",  "New York": "38.6",  "San Francisco": "57.7",  "Austin": "54.9"},
{"date": "20111031",  "New York": "44.2",  "San Francisco": "55.1",  "Austin": "58.8"},
{"date": "20111101",  "New York": "49.6",  "San Francisco": "57.9",  "Austin": "62.6"},
{"date": "20111102",  "New York": "47.2",  "San Francisco": "64.6",  "Austin": "71.0"},
{"date": "20111103",  "New York": "50.1",  "San Francisco": "56.2",  "Austin": "58.4"},
{"date": "20111104",  "New York": "50.1",  "San Francisco": "50.5",  "Austin": "45.1"},
{"date": "20111105",  "New York": "43.5",  "San Francisco": "51.3",  "Austin": "52.2"},
{"date": "20111106",  "New York": "43.8",  "San Francisco": "52.6",  "Austin": "73.0"},
{"date": "20111107",  "New York": "48.9",  "San Francisco": "51.4",  "Austin": "75.4"},
{"date": "20111108",  "New York": "55.5",  "San Francisco": "50.6",  "Austin": "72.1"},
{"date": "20111109",  "New York": "53.7",  "San Francisco": "54.6",  "Austin": "56.6"},
{"date": "20111110",  "New York": "57.7",  "San Francisco": "55.6",  "Austin": "55.4"},
{"date": "20111111",  "New York": "48.5",  "San Francisco": "53.9",  "Austin": "46.7"},
{"date": "20111112",  "New York": "46.8",  "San Francisco": "54.0",  "Austin": "62.0"},
{"date": "20111113",  "New York": "51.1",  "San Francisco": "53.8",  "Austin": "71.6"},
{"date": "20111114",  "New York": "56.8",  "San Francisco": "53.5",  "Austin": "75.5"},
{"date": "20111115",  "New York": "59.7",  "San Francisco": "53.4",  "Austin": "72.1"},
{"date": "20111116",  "New York": "56.5",  "San Francisco": "52.2",  "Austin": "65.7"},
{"date": "20111117",  "New York": "49.6",  "San Francisco": "52.7",  "Austin": "56.8"},
{"date": "20111118",  "New York": "41.5",  "San Francisco": "53.1",  "Austin": "49.9"},
{"date": "20111119",  "New York": "44.3",  "San Francisco": "49.0",  "Austin": "71.7"},
{"date": "20111120",  "New York": "54.0",  "San Francisco": "50.4",  "Austin": "77.7"},
{"date": "20111121",  "New York": "54.1",  "San Francisco": "51.1",  "Austin": "76.4"},
{"date": "20111122",  "New York": "49.4",  "San Francisco": "52.3",  "Austin": "68.8"},
{"date": "20111123",  "New York": "50.0",  "San Francisco": "54.6",  "Austin": "57.0"},
{"date": "20111124",  "New York": "44.0",  "San Francisco": "55.1",  "Austin": "55.5"},
{"date": "20111125",  "New York": "50.3",  "San Francisco": "51.5",  "Austin": "61.6"},
{"date": "20111126",  "New York": "52.1",  "San Francisco": "53.6",  "Austin": "64.1"},
{"date": "20111127",  "New York": "49.6",  "San Francisco": "52.3",  "Austin": "51.1"},
{"date": "20111128",  "New York": "57.2",  "San Francisco": "51.0",  "Austin": "43.0"}
];
    var margin = {
        top: 20,
        right: 80,
        bottom: 30,
        left: 50
      },
      width = 900 - margin.left - margin.right,
      height = 500 - margin.top - margin.bottom;

    var parseDate = d3.timeParse("%Y%m%d");

    var x = d3.scaleTime()
      .range([0, width]);

    var y = d3.scaleLinear()
      .range([height, 0]);

    var color = d3.scaleOrdinal(d3.schemeCategory10);

    var xAxis = d3.axisBottom()
      .scale(x);

    var yAxis = d3.axisLeft()
      .scale(y);

    var line = d3.line()
      .curve(d3.curveBasis)
      .x(function(d) {
        return x(d.date);
      })
      .y(function(d) {
        return y(d.temperature);
      });

    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 + ")");

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

    
    data.forEach(function(d) {
      // coerce input strings to number:
      d["San Francisco"] = +d["San Francisco"];
      d["Austin"] = +d["Austin"]
      d["New York"] = +d["New York"]
      
      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;
        });
      })
    ]);

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

    legend.append('rect')
      .attr('x', width - 20)
      .attr('y', function(d, i) {
        return i * 20;
      })
      .attr('width', 10)
      .attr('height', 10)
      .style('fill', function(d) {
        return color(d.name);
      });

    legend.append('text')
      .attr('x', width - 8)
      .attr('y', function(d, i) {
        return (i * 20) + 9;
      })
      .text(function(d) {
        return d.name;
      });

    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")
      .text("Temperature (ºF)");

    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;
      });

    var mouseG = svg.append("g")
      .attr("class", "mouse-over-effects");

    mouseG.append("path") 
      .attr("class", "mouse-line")
      .style("stroke", "black")
      .style("stroke-width", "1px")
      .style("opacity", "0");

    var lines = document.getElementsByClassName('line');

    var mousePerLine = mouseG.selectAll('.mouse-per-line')
      .data(cities)
      .enter()
      .append("g")
      .attr("class", "mouse-per-line");

    mousePerLine.append("circle")
      .attr("r", 7)
      .style("stroke", function(d) {
        return color(d.name);
      })
      .style("fill", "none")
      .style("stroke-width", "1px")
      .style("opacity", "0");

    mousePerLine.append("text")
      .attr("transform", "translate(10,3)");

    mouseG.append('svg:rect') // append a rect to catch mouse movements on canvas
      .attr('width', width) // can't catch mouse events on a g element
      .attr('height', height)
      .attr('fill', 'none')
      .attr('pointer-events', 'all')
      .on('mouseout', function() { // on mouse out hide line, circles and text
        d3.select(".mouse-line")
          .style("opacity", "0");
        d3.selectAll(".mouse-per-line circle")
          .style("opacity", "0");
        d3.selectAll(".mouse-per-line text")
          .style("opacity", "0");
      })
      .on('mouseover', function() { // on mouse in show line, circles and text
        d3.select(".mouse-line")
          .style("opacity", "1");
        d3.selectAll(".mouse-per-line circle")
          .style("opacity", "1");
        d3.selectAll(".mouse-per-line text")
          .style("opacity", "1");
      })
      .on('mousemove', function() { // mouse moving over canvas
        var mouse = d3.mouse(this);
        d3.select(".mouse-line")
          .attr("d", function() {
            var d = "M" + mouse[0] + "," + height;
            d += " " + mouse[0] + "," + 0;
            return d;
          });

        d3.selectAll(".mouse-per-line")
          .attr("transform", function(d, i) {
            console.log(width/mouse[0])
            var xDate = x.invert(mouse[0]),
                bisect = d3.bisector(function(d) { return d.date; }).right;
                idx = bisect(d.values, xDate);

            var beginning = 0,
                end = lines[i].getTotalLength(),
                target = null;

            while (true){
              target = Math.floor((beginning + end) / 2);
              pos = lines[i].getPointAtLength(target);
              if ((target === end || target === beginning) && pos.x !== mouse[0]) {
                  break;
              }
              if (pos.x > mouse[0])      end = target;
              else if (pos.x < mouse[0]) beginning = target;
              else break; //position found
            }

            d3.select(this).select('text')
              .text(y.invert(pos.y).toFixed(2));              
            return "translate(" + mouse[0] + "," + pos.y +")";
          });
      });  
    body {
      font: 10px sans-serif;
    }

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

    .x.axis path {
      display: none;
    }

    .line {
      fill: none;
      stroke: steelblue;
      stroke-width: 1.5px;
    }
<script src="https://d3js.org/d3.v5.min.js" charset="utf-8"></script>


 
     

正如您还希望将输入字符串强制转换为数字一样,将JSON字符串强制转换为data.forEach函数中的使用一元+的数字,您可以通过遍历每个属性来动态地做到这一点