javascript - D3.js: Wrong position of horizontal and vertical focus lines (crosshairs) in line chart -
i adapted example data: d3js graph x , y crosshairs, , threshold line.
it works pretty good, lines not shown on right point. see screenshot.
i think there problem domain, can't figure out. here script:
update: problem caused way position text. ideas how position text in way?
var svg = d3.select("svg"), margin = {top: 20, right: 50, bottom: 30, left: 50}, width = +svg.attr("width") - margin.left - margin.right, height = +svg.attr("height") - margin.top - margin.bottom, g = svg.append("g").attr("transform", "translate(" + margin.left + "," + margin.top + ")"); var parsetime = d3.utcparse("%y-%m-%dt%h:%m:%s.%lz"); var bisectdate = d3.bisector(function(d) { return d.timestamp; }).left; var formatvalue = d3.format(",.2f"); d3.json("data.json", function(error, json) { if (error) throw error; var data = json[0].tidedata; data.foreach(function(d) { d.timestamp = parsetime(d.timestamp); }); var xdomain = d3.extent(data, function(d) { return d.timestamp; }); var ydomain = d3.extent(data, function(d) { return d.tide; }); var xscale = d3.scaletime().rangeround([0, width]).domain(xdomain); var yscale = d3.scalelinear().rangeround([height, 0]).domain(ydomain); var line = d3.line() .defined(function(d) { return d.tide!=null; }) .x(function(d) { return xscale(d.timestamp); }) .y(function(d) { return yscale(d.tide); }); g.append("g") .attr("class", "axis axis--x") .attr("transform", "translate(0," + height + ")") .call(d3.axisbottom(xscale)); g.append("g") .attr("class", "axis axis--y") .call(d3.axisleft(yscale)) .append("text") .attr("fill", "#000") .attr("transform", "rotate(-90)") .attr("y", 6) .attr("dy", "0.71em") .style("text-anchor", "end") .text("sea level"); g.append("path") .datum(data) .attr("class", "line") .attr("d", line); var focus = g.append("g") .attr("class", "focus") .style("display", "none"); focus.append("circle") .attr("r", 4.5); focus.append("text") .attr("x", 9) .attr("dy", ".35em"); focus.append('line') .attr('id', 'focuslinex') .attr('class', 'focusline'); focus.append('line') .attr('id', 'focusliney') .attr('class', 'focusline'); g.append("rect") .attr("class", "overlay") .attr("width", width) .attr("height", height) .on("mouseover", function() { focus.style("display", null); }) .on("mouseout", function() { focus.style("display", "none"); }) .on("mousemove", mousemove); function mousemove() { var mouse = d3.mouse(this); var mousedate = xscale.invert(mouse[0]); var = bisectdate(data, mousedate); // returns index current data item var d0 = data[i - 1]; var d1 = data[i]; // work out date value closest mouse var d = mousedate - d0[0] > d1[0] - mousedate ? d1 : d0; var x = xscale(d.timestamp); var y = yscale(d.tide); focus.attr("transform", "translate(" + x + "," + y + ")"); focus.select("text").text(formatvalue(d.tide)); focus.select('#focuslinex') .attr('x1', x).attr('y1', yscale(ydomain[0])) .attr('x2', x).attr('y2', yscale(ydomain[1])); focus.select('#focusliney') .attr('x1', xscale(xdomain[0])).attr('y1', y) .attr('x2', xscale(xdomain[1])).attr('y2', y); } });
in code creating focus lines, using current data point(mouse position) start lines.
focus.select('#focuslinex') .attr('x1', x).attr('y1', yscale(ydomain[0])) .attr('x2', x).attr('y2', yscale(ydomain[1])); focus.select('#focusliney') .attr('x1', xscale(xdomain[0])).attr('y1', y) .attr('x2', xscale(xdomain[1])).attr('y2', y);
you horizontal line should start y axis , span on width @ hight of point. vertical line should start @ top of graph , go till bottom(x axis).
try change
focus.select('#focuslinex') .attr('x1', x).attr('y1', 0) .attr('x2', x).attr('y2', heightofchart); focus.select('#focusliney') .attr('x1', 0).attr('y1', y) .attr('x2', widthofchart).attr('y2', y);
hope helps
Comments
Post a Comment