本文介绍了鼠标移动和鼠标悬停时工具提示不显示的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用下面的代码创建带有工具提示的多折线图,并对其进行了一些自定义以使x轴序数化,并且我还对数据进行了编码.除工具提示外,其他所有内容似乎都正常运行.

https://bl.ocks.org/larsenmtl/e3b8b7c2ca4787f77d78f58d41c3da91

当我将鼠标悬停在数据点上时,工具提示不显示,并且我也试图使x轴离散,这意味着我希望看到数据变量中包含的数据而非x值的工具提示.在两者之间.

有人可以建议吗?

下面是我的代码:

     <head>
    <script data-require="d3@3.5.3" data-semver="3.5.3" src="//cdnjs.cloudflare.com/ajax/libs/d3/3.5.3/d3.js"></script>
      <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>
    </head>

    <body>
      <script>

        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.time.format("%Y%m%d").parse;

    //    var x = d3.scale.linear()
    //      .range([0, width]);
        var x  = d3.scale.ordinal()
        .domain(["20170101","20170108","20170115","20170122","20170128"])
        .rangePoints([0, width],0.5);

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

        var color = d3.scale.category10();

        var xAxis = d3.svg.axis()
          .scale(x)
    //      .ticks(5)
          .orient("bottom")
    //      .tickValues(["2017-01-01", "2017-01-08", "2017-01-15", "2017-01-22", "2017-01-28"]);

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

        var line = d3.svg.line()
          .interpolate("linear")
          .x(function(d) {
            return x(d.week);
          })
          .y(function(d) {
            return y(d.avg_test_drives);
          });

        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 data = d3.tsv.parse(myData);
    //      console.log(data[0]);
    //      alert (JSON.stringify(data));

        var data =  [{"week": "20170101", "dealer": "68", "peers": "73","all dealers":"123"},
                     {"week": "20170108", "dealer": "121","peers":"112","all dealers":"131"},
                     {"week": "20170115", "dealer": "104","peers":"101","all dealers":"106"},
                     {"week": "20170122", "dealer": "123","peers":"131","all dealers":"122"},
                     {"week": "20170128", "dealer": "106","peers":"107","all dealers":"122"}]
    //    alert (JSON.stringify(data));

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


        data.forEach(function(d) {
          d.week = d.week;
        });


        var testdrives = color.domain().map(function(name) {
          return {
            name: name,
            values: data.map(function(d) {
              return {
                week: d.week,
                avg_test_drives: +d[name]
              };
            })
          };
        });


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



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



        var legend = svg.selectAll('g')
          .data(testdrives)
          .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)
    //      .ticks(5);

        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("Test Drives");

        var entity = svg.selectAll(".entity")
          .data(testdrives)
          .enter().append("g")
          .attr("class", "entity");
    //    alert (JSON.stringify(entity));

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

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



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

        mouseG.append("path") // this is the black vertical line to follow mouse
          .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(testdrives)
          .enter()
          .append("g")
          .attr("class", "mouse-per-line");


        mousePerLine.append("circle")
          .attr("r", 7)
          .style("stroke", function(d) {
            return color(d.week);
          })
          .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.week; }).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 +")";
              });
          });

      </script>
    </body> 

解决方案

您试图访问x的函数invert(),但是由于它现在不是linear()而是ordinal(),因此无法反转它,而x = d3.scale.ordinal()缺少函数invert(),因此尝试调用此函数会导致错误并阻止下一行代码的执行,因此请注释掉:

 var xDate = x.invert(mouse[0]),
                    bisect = d3.bisector(function(d) { return d.week; }).right;
                    idx = bisect(d.values, xDate);

在d3.selectAll(".mouse-per-line")中,到这里,工具提示再次起作用:

     <head>
    <script data-require="d3@3.5.3" data-semver="3.5.3" src="//cdnjs.cloudflare.com/ajax/libs/d3/3.5.3/d3.js"></script>


      <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>
    </head>

    <body>
      <script>

        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.time.format("%Y%m%d").parse;

    //    var x = d3.scale.linear()
    //      .range([0, width]);
        var x  = d3.scale.ordinal()
        .domain(["20170101","20170108","20170115","20170122","20170128"])
        .rangePoints([0, width],0.5);

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

        var color = d3.scale.category10();

        var xAxis = d3.svg.axis()
          .scale(x)
    //      .ticks(5)
          .orient("bottom")
    //      .tickValues(["2017-01-01", "2017-01-08", "2017-01-15", "2017-01-22", "2017-01-28"]);

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

        var line = d3.svg.line()
          .interpolate("linear")
          .x(function(d) {
            return x(d.week);
          })
          .y(function(d) {
            return y(d.avg_test_drives);
          });

        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 data = d3.tsv.parse(myData);
    //      console.log(data[0]);
    //      alert (JSON.stringify(data));

        var data =  [{"week": "20170101", "dealer": "68", "peers": "73","all dealers":"123"},
                     {"week": "20170108", "dealer": "121","peers":"112","all dealers":"131"},
                     {"week": "20170115", "dealer": "104","peers":"101","all dealers":"106"},
                     {"week": "20170122", "dealer": "123","peers":"131","all dealers":"122"},
                     {"week": "20170128", "dealer": "106","peers":"107","all dealers":"122"}]
    //    alert (JSON.stringify(data));

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


        data.forEach(function(d) {
          d.week = d.week;
        });


        var testdrives = color.domain().map(function(name) {
          return {
            name: name,
            values: data.map(function(d) {
              return {
                week: d.week,
                avg_test_drives: +d[name]
              };
            })
          };
        });


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



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



        var legend = svg.selectAll('g')
          .data(testdrives)
          .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)
    //      .ticks(5);

        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("Test Drives");

        var entity = svg.selectAll(".entity")
          .data(testdrives)
          .enter().append("g")
          .attr("class", "entity");
    //    alert (JSON.stringify(entity));

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

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



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

        mouseG.append("path") // this is the black vertical line to follow mouse
          .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(testdrives)
          .enter()
          .append("g")
          .attr("class", "mouse-per-line");


        mousePerLine.append("circle")
          .attr("r", 7)
          .style("stroke", function(d) {
            return color(d.week);
          })
          .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.week; }).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 +")";
              });
          });

      </script>
    </body> 

I am using the below code to create a multi line chart with tool tips and have customized it a little bit to make the x axis ordinal and I have also har coded the data. Everything else seems to be working fine except for the tool tips.

https://bl.ocks.org/larsenmtl/e3b8b7c2ca4787f77d78f58d41c3da91

The tool tips dont show up when I hover over the data points and I am also trying to make the x axis discrete meaning I wish to see the tool tips for the data I have in the data variable and not for the x values in between.

could someone please advise ?

Below is my code:

    <head>
    <script data-require="d3@3.5.3" data-semver="3.5.3" src="//cdnjs.cloudflare.com/ajax/libs/d3/3.5.3/d3.js"></script>
      <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>
    </head>

    <body>
      <script>

        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.time.format("%Y%m%d").parse;

    //    var x = d3.scale.linear()
    //      .range([0, width]);
        var x  = d3.scale.ordinal()
        .domain(["20170101","20170108","20170115","20170122","20170128"])
        .rangePoints([0, width],0.5);

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

        var color = d3.scale.category10();

        var xAxis = d3.svg.axis()
          .scale(x)
    //      .ticks(5)
          .orient("bottom")
    //      .tickValues(["2017-01-01", "2017-01-08", "2017-01-15", "2017-01-22", "2017-01-28"]);

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

        var line = d3.svg.line()
          .interpolate("linear")
          .x(function(d) {
            return x(d.week);
          })
          .y(function(d) {
            return y(d.avg_test_drives);
          });

        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 data = d3.tsv.parse(myData);
    //      console.log(data[0]);
    //      alert (JSON.stringify(data));

        var data =  [{"week": "20170101", "dealer": "68", "peers": "73","all dealers":"123"},
                     {"week": "20170108", "dealer": "121","peers":"112","all dealers":"131"},
                     {"week": "20170115", "dealer": "104","peers":"101","all dealers":"106"},
                     {"week": "20170122", "dealer": "123","peers":"131","all dealers":"122"},
                     {"week": "20170128", "dealer": "106","peers":"107","all dealers":"122"}]
    //    alert (JSON.stringify(data));

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


        data.forEach(function(d) {
          d.week = d.week;
        });


        var testdrives = color.domain().map(function(name) {
          return {
            name: name,
            values: data.map(function(d) {
              return {
                week: d.week,
                avg_test_drives: +d[name]
              };
            })
          };
        });


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



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



        var legend = svg.selectAll('g')
          .data(testdrives)
          .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)
    //      .ticks(5);

        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("Test Drives");

        var entity = svg.selectAll(".entity")
          .data(testdrives)
          .enter().append("g")
          .attr("class", "entity");
    //    alert (JSON.stringify(entity));

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

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



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

        mouseG.append("path") // this is the black vertical line to follow mouse
          .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(testdrives)
          .enter()
          .append("g")
          .attr("class", "mouse-per-line");


        mousePerLine.append("circle")
          .attr("r", 7)
          .style("stroke", function(d) {
            return color(d.week);
          })
          .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.week; }).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 +")";
              });
          });

      </script>
    </body>

解决方案

You was trying to access function invert() of x, however since it is not linear() but ordinal() now, it is not possible to invert it, and function invert() is missing for x = d3.scale.ordinal(), thus trying to call this function was causing an error and blocking the execution of the next lines of code, so just comment out:

 var xDate = x.invert(mouse[0]),
                    bisect = d3.bisector(function(d) { return d.week; }).right;
                    idx = bisect(d.values, xDate);

in d3.selectAll(".mouse-per-line") and here you go, tooltip is working again:

    <head>
    <script data-require="d3@3.5.3" data-semver="3.5.3" src="//cdnjs.cloudflare.com/ajax/libs/d3/3.5.3/d3.js"></script>


      <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>
    </head>

    <body>
      <script>

        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.time.format("%Y%m%d").parse;

    //    var x = d3.scale.linear()
    //      .range([0, width]);
        var x  = d3.scale.ordinal()
        .domain(["20170101","20170108","20170115","20170122","20170128"])
        .rangePoints([0, width],0.5);

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

        var color = d3.scale.category10();

        var xAxis = d3.svg.axis()
          .scale(x)
    //      .ticks(5)
          .orient("bottom")
    //      .tickValues(["2017-01-01", "2017-01-08", "2017-01-15", "2017-01-22", "2017-01-28"]);

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

        var line = d3.svg.line()
          .interpolate("linear")
          .x(function(d) {
            return x(d.week);
          })
          .y(function(d) {
            return y(d.avg_test_drives);
          });

        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 data = d3.tsv.parse(myData);
    //      console.log(data[0]);
    //      alert (JSON.stringify(data));

        var data =  [{"week": "20170101", "dealer": "68", "peers": "73","all dealers":"123"},
                     {"week": "20170108", "dealer": "121","peers":"112","all dealers":"131"},
                     {"week": "20170115", "dealer": "104","peers":"101","all dealers":"106"},
                     {"week": "20170122", "dealer": "123","peers":"131","all dealers":"122"},
                     {"week": "20170128", "dealer": "106","peers":"107","all dealers":"122"}]
    //    alert (JSON.stringify(data));

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


        data.forEach(function(d) {
          d.week = d.week;
        });


        var testdrives = color.domain().map(function(name) {
          return {
            name: name,
            values: data.map(function(d) {
              return {
                week: d.week,
                avg_test_drives: +d[name]
              };
            })
          };
        });


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



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



        var legend = svg.selectAll('g')
          .data(testdrives)
          .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)
    //      .ticks(5);

        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("Test Drives");

        var entity = svg.selectAll(".entity")
          .data(testdrives)
          .enter().append("g")
          .attr("class", "entity");
    //    alert (JSON.stringify(entity));

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

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



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

        mouseG.append("path") // this is the black vertical line to follow mouse
          .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(testdrives)
          .enter()
          .append("g")
          .attr("class", "mouse-per-line");


        mousePerLine.append("circle")
          .attr("r", 7)
          .style("stroke", function(d) {
            return color(d.week);
          })
          .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.week; }).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 +")";
              });
          });

      </script>
    </body>

这篇关于鼠标移动和鼠标悬停时工具提示不显示的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-18 00:07
查看更多