2013-12-13 80 views
3

我正在使用d3库绘制线图。d3.js:垂直移动线与线图的交点

以下是我的代码来生成折线图。

<html> 
<head> 
    <title>Simple Line Graph using SVG and d3.js</title> 
    <script src="http://mbostock.github.com/d3/d3.v2.js"></script> 
    <style> 
     /* tell the SVG path to be a thin blue line without any area fill */ 
     path { 
      stroke: steelblue; 
      stroke-width: 1; 
      fill: none; 
     } 

     .axis { 
      shape-rendering: crispEdges; 
     } 

     .x.axis line { 
      stroke: lightgrey; 
     } 

     .x.axis .minor { 
      stroke-opacity: .5; 
     } 

     .x.axis path { 
      display: none; 
     } 

     .y.axis line, .y.axis path { 
      fill: none; 
      stroke: #000; 
     } 
    </style> 
</head> 
<body> 


    <div id="graph" class="aGraph" style="position:absolute;top:0px;left:0; float:left;"></div> 


    <script> 
     /* implementation heavily influenced by http://bl.ocks.org/1166403 */ 

     // define dimensions of graph 
     var m = [80, 80, 80, 80]; // margins 
     var w = 1000 - m[1] - m[3]; // width 
     var h = 400 - m[0] - m[2]; // height 

     // create a simple data array that we'll plot with a line (this array represents only the Y values, X will just be the index location) 
     var data = [3, 6, 2, 7, 5, 2, 0, 3, 8, 9, 2, 5, 9, 3, 6, 3, 6, 2, 7, 5, 2, 1, 3, 8, 9, 2, 5, 9, 2, 7]; 

     // X scale will fit all values from data[] within pixels 0-w 
     var x = d3.scale.linear().domain([0, data.length]).range([0, w]); 
     // Y scale will fit values from 0-10 within pixels h-0 (Note the inverted domain for the y-scale: bigger is up!) 
     var y = d3.scale.linear().domain([0, 10]).range([h, 0]); 
     // automatically determining max range can work something like this 
     // var y = d3.scale.linear().domain([0, d3.max(data)]).range([h, 0]); 

     // create a line function that can convert data[] into x and y points 
     var line = d3.svg.line() 
       // assign the X function to plot our line as we wish 
       .x(function(d, i) { 
        // verbose logging to show what's actually being done 
        console.log('Plotting X value for data point: ' + d + ' using index: ' + i + ' to be at: ' + x(i) + ' using our xScale.'); 
        // return the X coordinate where we want to plot this datapoint 
        return x(i); 
       }) 
       .y(function(d) { 
        // verbose logging to show what's actually being done 
        console.log('Plotting Y value for data point: ' + d + ' to be at: ' + y(d) + " using our yScale."); 
        // return the Y coordinate where we want to plot this datapoint 
        return y(d); 
       }) 

     // Add an SVG element with the desired dimensions and margin. 
     var graph = d3.select("#graph").append("svg:svg") 
       .attr("width", w + m[1] + m[3]) 
       .attr("height", h + m[0] + m[2]) 
       .append("svg:g") 
       .attr("transform", "translate(" + m[3] + "," + m[0] + ")"); 

     // create yAxis 
     var xAxis = d3.svg.axis().scale(x).tickSize(-h).tickSubdivide(true); 
     // Add the x-axis. 
     graph.append("svg:g") 
       .attr("class", "x axis") 
       .attr("transform", "translate(0," + h + ")") 
       .call(xAxis); 


     // create left yAxis 
     var yAxisLeft = d3.svg.axis().scale(y).ticks(4).orient("left"); 
     // Add the y-axis to the left 
     graph.append("svg:g") 
       .attr("class", "y axis") 
       .attr("transform", "translate(-25,0)") 
       .call(yAxisLeft); 

     // Add the line by appending an svg:path element with the data line we created above 
     // do this AFTER the axes above so that the line is above the tick-lines 
     graph.append("svg:path").attr("d", line(data)); 

     var line1 = graph.append('line') 
       .attr('transform', 'translate(100, 50)') 
       .attr({'x1': 0, 'y1': 0, 'x2': 0, 'y2': 1400}) 
       .attr('class', 'selection_line'); 
     graph.on('mousemove', function(e) { 
      var navigatorVersion = navigator.appVersion; 
      var navigatorAgent = navigator.userAgent; 
      var browserName = navigator.appName; 
      var fullVersionName = '' + parseFloat(navigator.appVersion); 
      var majorVersionName = parseInt(navigator.appVersion, 10); 
      var nameOffset, verOffset, ix; 
      // In Firefox, the true version is after "Firefox" 
      //To make line scroll horizontally in mozilla firefox use following code  
      if ((verOffset = navigatorAgent.indexOf("Firefox")) != -1) { 
       browserName = "Firefox"; 
       fullVersionName = navigatorAgent.substring(verOffset + 8); 
      } 
      if (browserName == "Firefox") { 
       line1.attr("x1", d3.event.clientX - 100); 
       line1.attr("x2", d3.event.clientX - 100); 
      } 
      else { 
       line1.attr("x1", d3.event.x - 100); 
       line1.attr("x2", d3.event.x - 100); 
      } 
     }); 



    </script> 



</body> 
</html> 

上鼠标移动我想移动一个垂直线与鼠标和希望找到与线图的垂直线的交点。即找到垂直线与图形相交的线图的x和y坐标。

任何想法为什么它不工作?

+1

[这个问题](http://stackoverflow.com/questions/18882642/d3-js-drawing-a-line-on-linegraph-on-mouseover)应该有所帮助。 –

+0

这个错误,没有任何上下文,没有告诉我任何事情。 –

+0

这是由于我认为这条线。 var div_width = parseInt(d3.select('body')。style('width')。replace('px','')); – asdfdefsad

回答

6

这里工作你图的版本有很多的变化 - http://jsfiddle.net/cuckovic/vKe67/

这里是做“繁重”的代码:

rect.on('mousemove', function() { 

var xPos = d3.mouse(this)[0]; 
d3.select(".verticalLine").attr("transform", function() { 
    return "translate(" + xPos + ",0)"; 
}); 


var pathLength = mainLine.node().getTotalLength(); 
var x = xPos; 
var beginning = x, 
    end = pathLength, 
    target; 
while (true) { 
    target = Math.floor((beginning + end)/2); 
    pos = mainLine.node().getPointAtLength(target); 
    if ((target === end || target === beginning) && pos.x !== x) { 
     break; 
    } 
    if (pos.x > x) end = target; 
    else if (pos.x < x) beginning = target; 
    else break; //position found 
} 
circle.attr("opacity", 1) 
    .attr("cx", x) 
    .attr("cy", pos.y); 


console.log("x and y coordinate where vertical line intersects graph: " + [pos.x, pos.y]); 
console.log("data where vertical line intersects graph: " + [xScale.invert(pos.x), yScale.invert(pos.y)]); 
}); 

问候, 伊戈尔

+0

找到交叉点,如果我有两个图形和一个单一的垂直线穿越两者我想找出与两个图形垂直线的交点http://jsfiddle.net/2SURM/ – asdfdefsad

+0

它可以通过将完成第二个图形在第一个图形下面的同一个“rect”元素上,然后修改计算中使用的所有变量。基本上你必须复制第一个图。 – cuckovic

+0

@cukovic可以解释目标= Math.floor((开始+结束)/ 2)中实际发生的情况; pos = mainLine.node()。getPointAtLength(target); 如果((目标===结束||目标===开始)&& pos.x == X!){ 休息; } if(pos.x> x)end = target; 否则如果(pos.x asdfdefsad