javascript - d3: how to snap mouse over cursor to existing data points -


in following snippet (based on answer of @gerardo furtado d3 multi line mouse on cursor both y , x value) mouse on cursor interpolating values between data points.

how possible cursor shows values real data points?

<!doctype html>  <html>    <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;      }            .x.axis path {        display: none;      }            .line {        fill: none;        stroke: steelblue;        stroke-width: 1.5px;      }    </style>  </head>    <body>    <script>      var mydata = "date	new york	san francisco	austin\n\  20111001	63.4	62.7	72.2\n\  20111002	58.0	59.9	67.7\n\  20111006	58.8	57.0	77.0\n\  20111007	57.9	56.7	82.3\n\  20111008	61.8	56.8	78.9\n\  20111009	69.3	56.7	68.8\n\  20111010	71.2	60.1	68.7\n\  20111015	61.7	64.6	68.0\n\  20111016	61.8	61.6	70.6\n\  20111017	62.8	61.1	71.1\n\  20111018	60.8	59.2	70.0\n\  20111022	54.4	60.7	72.4\n";        var margin = {          top: 20,          right: 80,          bottom: 30,          left: 50        },        width = 500 - margin.left - margin.right,        height = 500 - margin.top - margin.bottom;        var parsedate = d3.time.format("%y%m%d").parse;      var parsedate2 = d3.time.format("%y/%m/%d");        var x = d3.time.scale()        .range([0, width]);        var y = d3.scale.linear()        .range([height, 0]);        var color = d3.scale.category10();        var xaxis = d3.svg.axis()        .scale(x)        .orient("bottom");        var yaxis = d3.svg.axis()        .scale(y)        .orient("left");        var line = d3.svg.line()        .interpolate("linear")        .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 + ")");        var data = d3.tsv.parse(mydata);        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 * 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") // black vertical line 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(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 rect catch mouse movements on canvas        .attr('width', width) // can't catch mouse events on g element        .attr('height', height)        .attr('fill', 'none')        .attr('pointer-events', 'all')        .on('mouseout', function() { // on mouse out hide line, circles , 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 , 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 on 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) {                          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) + " - "                 + parsedate2(xdate));                              return "translate(" + mouse[0] + "," + pos.y +")";            });        });            </script>  </body>    </html>


Comments

Popular posts from this blog

php - Permission denied. Laravel linux server -

google bigquery - Delta between query execution time and Java query call to finish -

python - Pandas two dataframes multiplication? -