2013-12-13 105 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