【问题标题】:d3.js:vertical moving line's intersection point with line graphd3.js:垂直移动线与折线图的交点
【发布时间】:2013-12-13 09:20:32
【问题描述】:

我正在使用 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坐标。

知道为什么它不起作用吗?

【问题讨论】:

  • This question 应该会有所帮助。
  • 那个错误,没有任何上下文,没有告诉我任何事情。
  • 我认为是因为这条线。 var div_width = parseInt(d3.select('body').style('width').replace('px', ''));
  • 好的,那么您是否尝试过替换该行以查看是否可以正常工作?
  • 我试过删除这两行 var div_width = parseInt(d3.select('body').style('width').replace('px','')); var graph_width = (div_width > 695) ? div_width:695;错误消失了,但图表不显示

标签: javascript jquery d3.js


【解决方案1】:

这是你的图表的工作版本,有很多变化 - 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)]);
});

问候, 伊戈尔

【讨论】:

  • 如果我有两个图形并且一条垂直线穿过它们,如何找到交点我想找出垂直线与两个图形的交点jsfiddle.net/2SURM
  • 这可以通过将第二个图放在第一个图下方的相同“rect”元素上然后修改计算中使用的所有变量来完成。基本上你必须复制第一张图。
  • @cukovic 你能解释一下 target = Math.floor((beginning + end) / 2); 中实际发生的事情吗? pos = mainLine.node().getPointAtLength(target); if ((target === end || target === begin) && pos.x !== x) { break; } if (pos.x > x) end = target;否则 if (pos.x
猜你喜欢
  • 2017-10-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多