为折线图创建D3工具提示的问题

时间:2015-02-09 19:55:39

标签: d3.js tooltip linegraph

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

TypeError:第137行未定义d1

我一直在寻找解决方案但尚未找到任何帮助,所以任何帮助都会得到赞赏。

下面是代码:

 <!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>

1 个答案:

答案 0 :(得分:2)

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

这里有几个问题。

首先,您的数据没有按日期排序(从最早到最晚),这阻止bisectYear功能正常工作(它始终返回1)。修正了:

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

其次,您的日期(年)值未被解析为Date个对象,这导致了一系列问题。从本质上讲,你的时间尺度从1891ms到2014ms,而不是1891年到2014年!我在您阅读CSV时添加了这个:

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

使用新功能根据全年解析为Date

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