【问题标题】:Issues creating a D3 tooltip for line graph为折线图创建 D3 工具提示的问题
【发布时间】:2015-02-09 19:55:38
【问题描述】:

我正在尝试从该站点 (http://www.d3noob.org/2014/07/my-favourite-tooltip-method-for-line.html) 为我的双轴线​​图重新创建工具提示。但是我一直遇到一个错误,圆圈只出现在图表的右上角,我得到了错误

TypeError: d1 在第 137 行未定义

我一直在寻找解决方案,但还没有找到任何帮助。

代码如下:

 <!DOCTYPE html>
 <html>
 <head>
 <script type="text/javascript" src="d3/d3.min.js"></script>
 </head>
 <body>
 <script type="text/javascript">

 // http://www.baseball-reference.com/teams/PIT/attend.shtml

 /* want interactive line chart showing two lines, total attendance and      attendance per game
    cicles at vaious points that show information on hover about why attendance may be drastically different
    ie opening of pnc park or world series team */

// Set the dimensions of the canvas / graph
var margin = {top: 30, right: 50, bottom: 30, left: 150},
    width = 1000 - margin.left - margin.right,
    height = 400 - margin.top - margin.bottom;

// Method used for finding year corresponding with mouse location   
var bisectYear = d3.bisector(function(d) { return d.Year; }).left;

// Set the ranges
var x = d3.time.scale().range([0, width]);
var y0 = d3.scale.linear().range([height, 0]);
var y1 = d3.scale.linear().range([height, 0]);

// Define the axes
var xAxis = d3.svg.axis().scale(x)
    .tickFormat(d3.format(".0f"))
    .orient("bottom");

var yAxisLeft = d3.svg.axis().scale(y0)
    .orient("left")
    .ticks(5);

var yAxisRight = d3.svg.axis().scale(y1)
    .orient("right").ticks(5)

// Define the first line
var valueline = d3.svg.line()
    .x(function(d) { return x(d.Year); })
    .y(function(d) { return y0(d.AttendancePerG); });

// Define the second line
var valueline2 = d3.svg.line()
    .x(function(d) { return x(d.Year); })
    .y(function(d) { return y1(d.Wins); });

// Adds the svg canvas
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 lineSvg = svg.append("g");                             // **********

var focus = svg.append("g")                                // **********
    .style("display", "none");                             // **********
///////////////////

// Get the data
d3.csv("piratesAttendance.csv", function(error, data) {
    data.forEach(function(d) {
        d.Year = +d.Year;
        d.AttendancePerG = +d.AttendancePerG
        d.Wins = +d.Wins;
    });

    // Scale the range of the data
    x.domain(d3.extent(data, function(d) { return d.Year; }));
    y0.domain([0, d3.max(data, function(d) { return d.AttendancePerG; })]);
    y1.domain([0, d3.max(data, function(d) { return d.Wins; })]);

    // Add the valueline path.
    svg.append("path")
        .attr("class", "line")
        .attr("d", valueline(data))
        .attr("stroke", "gray")
        .attr("stroke-width",2)
        .attr("fill","none");

    // Add the second valueline path.
    svg.append("path")
        .attr("class", "line")
        .attr("d", valueline2(data))
        .attr("stroke", "gold")
        .attr("stroke-width",2)
        .attr("fill","none");

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

    // Add the Left Y Axis
    svg.append("g")
        .attr("class", "y axis")
        .style("fill","gray")
        .call(yAxisLeft);

    // Add the Right Y Axis
    svg.append("g")
        .attr("class", "y axis")
        .attr("transform", "translate(" + width + ",0)")
        .style("fill","gold")
        .call(yAxisRight);

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

    // 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() { focus.style("display", null); })
        .on("mouseout", function() { focus.style("display", "none"); })
        .on("mousemove", mousemove);                       // **********

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

    focus.select("circle.y")                           // **********
        .attr("transform",                             // **********
              "translate(" + x(d.Year) + "," +         // **********
                             y0(d.AttendancePerG) + ")");        // **********
}                                                      // **********
});

 </script>
 </body>
 </html>

【问题讨论】:

  • 你能把它变成一个 jsfiddle 或一个 plunk 以便我们看到问题吗?或者至少分享一下piratesAttendance.csv 的样子?
  • 不知道为什么你会得到d1 is undefined,至少,不是没有看到你的数据和调试一些东西,但d = x0 - d0.date &gt; d1.date - x0 ? d1 : d0;不应该是d = x0 - d0.Year &gt; d1.Year - x0 ? d1 : d0;
  • @HenryS 继承了 jsfiddle 与 html 中的 csv jsfiddle.net/SR34/1dtvxrjk/#&togetherjs=91PUASCGP7
  • @BenLyall 你说得对,应该是 d0.Year 和 d1.Year 谢谢你的收获

标签: d3.js tooltip linegraph


【解决方案1】:

这里有一个固定代码:http://plnkr.co/edit/Xj2ZyxqrY2PJVV0FML26

这里有几个问题。

首先,您的数据没有按日期排序(从最早到最新),这导致bisectYear 函数无法正常工作(它总是返回1)。通过添加修复:

data.sort(function(a, b) { return a.Year - b.Year; });

其次,您的日期(年份)值没有被解析为 Date 对象,这导致了一系列问题。本质上,您的时间尺度是从 1891 毫秒到 2014 毫秒,而不是从 1891 年到 2014 年!我在您在 CSV 中阅读的位置添加了此内容:

data.forEach(function(d) {
    d.Year =  parseDate(d.Year)
    ...

使用一个新函数来解析为 Date 仅基于全年:

var parseDate = d3.time.format("%Y").parse;

【讨论】:

  • 我想我的印象是,由于没有时间日月元素,我不需要将年份视为日期。这很好用,非常感谢@HenryS
猜你喜欢
  • 1970-01-01
  • 2017-06-24
  • 1970-01-01
  • 2015-07-16
  • 1970-01-01
  • 1970-01-01
  • 2013-08-29
  • 2021-06-16
  • 1970-01-01
相关资源
最近更新 更多