2016-11-10 140 views
0

水平和垂直聚焦线(十字线)的错误的位置I适于我的数据这个例子: D3js Graph with X and Y crosshairs, and a threshold lineD3.js:在折线图

它的工作原理相当不错,但行不上点右键所示。看截图。 enter image description here

我认为这个域存在问题,但我无法弄清楚。这里是我的脚本:

更新:该问题是由我的位置文本的方式造成的。任何想法如何以另一种方式来定位文本?

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 i = bisectDate(data, mouseDate); // returns the index to the current data item 

     var d0 = data[i - 1]; 
     var d1 = data[i]; 
     // work out which date value is closest to the 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); 

    } 
}); 

回答

0

的问题是整个焦点变量的转变。我分别定位了圆圈和文本,现在它可以工作:

 // focus tracking 

     var focus = g.append('g').style('display', 'none') 

     focus.append('circle') 
       .attr('id', 'focusCircle') 
       .attr('r', 4.5) 
       .attr('class', 'circle focusCircle') 

     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 i = bisectDate(data, mouseDate) // returns the index to the current data item 

      var d0 = data[i - 1] 
      var d1 = data[i] 
      // work out which date value is closest to the mouse 
      var d = mouseDate - d0[0] > d1[0] - mouseDate ? d1 : d0 

      var x = xScale(d.date) 
      var y = yScale(d.tide) 

      focus.select("text") 
        .attr("transform", "translate(" + x + "," + y + ")") 
        .text(formatValue(d.tide)) 

      focus.select('#focusCircle') 
        .attr('cx', x) 
        .attr('cy', y) 

      focus.select('#focusLineX') 
        .attr('x1', xScale(d.date)).attr('y1', yScale(yDomain[0])) 
        .attr('x2', xScale(d.date)).attr('y2', yScale(yDomain[1])) 
      focus.select('#focusLineY') 
        .attr('x1', xScale(xDomain[0])).attr('y1', yScale(d.tide)) 
        .attr('x2', xScale(xDomain[1])).attr('y2', yScale(d.tide)) 

     } 
0

在创建焦点线的代码中,您正在使用当前数据点(鼠标位置)来启动线条。

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); 

你的水平线应该从y轴开始,跨越你的点高度的宽度。同样,垂直线应该从图的顶部开始,直到底部(x轴)。

试试这个变化

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); 

希望它可以帮助

+0

不幸的是,它不起作用。这与之前的结果是一样的。 – Felix