score:1

Accepted answer

I'm not sure what part you are having trouble with.

I took d3noob's example and converted the "date" to numeric:

date,close
0,606.98
10,614.48
20,617.62
30,609.86
40,599.55
50,618.63
60,629.32
70,624.31
80,633.68
90,636.23
100,628.44
110,626.20

I changed the scale:

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

I then "fixed" the data.forEach to remove the date coercion:

data.forEach(function(d) {
    d.date = +d.date; //<-- treat date as number
    d.close = +d.close; 
});

And finally removed the formatDate calls in the mousemove.

Everything still works, here is a link to it running.


Full code:

<!DOCTYPE html>
<meta charset="utf-8">
<style> /* set the CSS */

body { font: 12px Arial;}

path { 
    stroke: steelblue;
    stroke-width: 2;
    fill: none;
}

.axis path,
.axis line {
    fill: none;
    stroke: grey;
    stroke-width: 1;
    shape-rendering: crispEdges;
}

</style>
<body>

<!-- load the d3.js library -->    
<script src="http://d3js.org/d3.v3.min.js"></script>

<script>

// Set the dimensions of the canvas / graph
var margin = {top: 30, right: 20, bottom: 30, left: 50},
    width = 600 - margin.left - margin.right,
    height = 270 - margin.top - margin.bottom;
    
var bisectDate = d3.bisector(function(d) { return d.date; }).left;

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

// Define the axes
var xAxis = d3.svg.axis().scale(x)
    .orient("bottom").ticks(5);

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

// Define the line
var valueline = d3.svg.line()
    .x(function(d) { return x(d.date); })
    .y(function(d) { return y(d.close); });
    
// 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("atad.csv", function(error, data) {
  
    var data = [{"date":"0","close":"606.98"},{"date":"10","close":"614.48"},{"date":"20","close":"617.62"},{"date":"30","close":"609.86"},{"date":"40","close":"599.55"},{"date":"50","close":"618.63"},{"date":"60","close":"629.32"},{"date":"70","close":"624.31"},{"date":"80","close":"633.68"},{"date":"90","close":"636.23"},{"date":"100","close":"628.44"},{"date":"110","close":"626.20"},{"date":"120","close":"622.77"},{"date":"130","close":"605.23"},{"date":"140","close":"580.13"},{"date":"150","close":"543.70"},{"date":"160","close":"443.34"},{"date":"170","close":"345.44"},{"date":"180","close":"234.98"},{"date":"190","close":"166.70"},{"date":"200","close":"130.28"},{"date":"210","close":"99.00"},{"date":"220","close":"89.70"},{"date":"230","close":"67.00"},{"date":"240","close":"53.98"},{"date":"250","close":"58.13"}];
    
    data.forEach(function(d) {
        d.date = +d.date;
        d.close = +d.close;
    });

    // Scale the range of the data
    x.domain(d3.extent(data, function(d) { return d.date; }));
    y.domain([0, d3.max(data, function(d) { return d.close; })]);

    // Add the valueline path.
    lineSvg.append("path")
        .attr("class", "line")
        .attr("d", valueline(data));

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

    // Add the Y Axis
    svg.append("g")
        .attr("class", "y axis")
        .call(yAxis);

   // append the x line
    focus.append("line")
        .attr("class", "x")
        .style("stroke", "blue")
        .style("stroke-dasharray", "3,3")
        .style("opacity", 0.5)
        .attr("y1", 0)
        .attr("y2", height);

    // append the y line
    focus.append("line")
        .attr("class", "y")
        .style("stroke", "blue")
        .style("stroke-dasharray", "3,3")
        .style("opacity", 0.5)
        .attr("x1", width)
        .attr("x2", width);

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

    // place the value at the intersection
    focus.append("text")
        .attr("class", "y1")
        .style("stroke", "white")
        .style("stroke-width", "3.5px")
        .style("opacity", 0.8)
        .attr("dx", 8)
        .attr("dy", "-.3em");
    focus.append("text")
        .attr("class", "y2")
        .attr("dx", 8)
        .attr("dy", "-.3em");

    // place the date at the intersection
    focus.append("text")
        .attr("class", "y3")
        .style("stroke", "white")
        .style("stroke-width", "3.5px")
        .style("opacity", 0.8)
        .attr("dx", 8)
        .attr("dy", "1em");
    focus.append("text")
        .attr("class", "y4")
        .attr("dx", 8)
        .attr("dy", "1em");
    
    // 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 = bisectDate(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.date) + "," +
		                         y(d.close) + ")");

		focus.select("text.y1")
		    .attr("transform",
		          "translate(" + x(d.date) + "," +
		                         y(d.close) + ")")
		    .text(d.close);

		focus.select("text.y2")
		    .attr("transform",
		          "translate(" + x(d.date) + "," +
		                         y(d.close) + ")")
		    .text(d.close);

		focus.select("text.y3")
		    .attr("transform",
		          "translate(" + x(d.date) + "," +
		                         y(d.close) + ")")
		    .text(d.date);

		focus.select("text.y4")
		    .attr("transform",
		          "translate(" + x(d.date) + "," +
		                         y(d.close) + ")")
		    .text(d.date);

		focus.select(".x")
		    .attr("transform",
		          "translate(" + x(d.date) + "," +
		                         y(d.close) + ")")
		               .attr("y2", height - y(d.close));

		focus.select(".y")
		    .attr("transform",
		          "translate(" + width * -1 + "," +
		                         y(d.close) + ")")
		               .attr("x2", width + width);
	}

//});

</script>
</body>

score:2

Do you mean something like this? https://jsfiddle.net/gerardofurtado/ayta89cz/5/

In this fiddle I'm just using d3.mouse() to get the position of the mouse over the transparent rectangle, and using two dashed lines for the crosshair. You can easily convert these values to the relative x-scale and y-scale values. I hardcoded the math here because I knew the slope of the trendline I just created, but you have to modify the math according to your trendline.


Related Query