d3.js:垂直移动线与线图的交点

时间:2013-12-13 09:20:33

标签: javascript jquery d3.js

我正在使用d3库绘制折线图。

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

<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 个答案:

答案 0 :(得分: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)]);
});

此致 伊戈尔