图中的点移动时更新路径

时间:2018-08-08 16:11:53

标签: d3.js

我正在处理包含3个点的图形。 (0,0),(5,5),(10,10)。用户可以在y轴上移动这些点。目前,我可以在Y轴上移动这些点,但是当其中之一移动时,无法“更新”这些点之间的路径。

我会提供任何帮助,谢谢!

这是代码,我正在使用d3js v4:

<script>
    // Set the dimension of the canvas / graph
    var margin = { top: 30, right: 20, bottom: 30, left: 50 };
    var width = 600 - margin.left - margin.right;
    var height = 500 - margin.top - margin.bottom;

    // Add the svg canvas
    var svg = d3.select("body")
        .append("svg")
        .attr("width", width + margin.left + margin.right)
        .attr("height", height + margin.top + margin.bottom)
        .append("g")
        .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

    // Set the linear scale and the range for the axes
    var xRange = d3.scaleLinear().range([0, width]).domain([0, 10]);
    var yRange = d3.scaleLinear().range([height, 0]).domain([0, 10]);

    var line = d3.line()
        .x(d => xRange(d.x))
        .y(d => yRange(d.y))
        .curve(d3.curveLinear);

    var drag = d3.drag()
        .on("drag", function (d) {
            var dragPoint = d3.select(this);
            dragPoint.attr("cy", d.y = d3.event.y);
        });

    // Points dataset
    var radius = 6;
    var points = [{ x: 0, y: 0 }, { x: 5, y: 5 }, { x: 10, y: 10 }];

    // Add the X axis
    svg.append("g")
        .attr("transform", "translate(0," + height + ")")
        .call(d3.axisBottom(xRange));

    // Add the Y axis
    svg.append("g")
        .call(d3.axisLeft(yRange));

    // Add points to the svg
    var circles = svg.attr("class", "circle")
        .selectAll("circle")
        .data(points)
        .enter()
        .append("circle")
        .attr("cx", d => xRange(d.x))
        .attr("cy", d => yRange(d.y))
        .attr("r", radius)
        .attr("fill", "teal")
        .style("cursor", "pointer");

    // Add the path
    var path = svg.append("path")
        .attr("d", line(points));

    drag(circles);
</script>

1 个答案:

答案 0 :(得分:0)

您的drag几乎不需要调整。

使用https://stackoverflow.com/a/38650810/9938317更改了起始对象,因此我们开始在圆形位置拖动。

然后,我们需要将这一点的y值反转并将其填充到基准对象中。为了限制拖动超出轴域,我们首先将其钳位到该域。

然后,我们根据更新后的path数组来更新points

var drag = d3.drag()
    .subject(function() { 
        var t = d3.select(this);
        return {x: t.attr("cx"), y: t.attr("cy")};
    })
    .on("drag", function (d) {
        var domain = yRange.domain();
        d.y = Math.max(domain[0], Math.min(yRange.invert(d3.event.y), domain[1]))
        d3.select(this).attr("cy", yRange(d.y));
        path.attr("d", line(points));
    });

完整的示例

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<script src="https://d3js.org/d3.v5.min.js"></script>
<style>
.line {stroke:steelblue; fill:none;}
</style>
</head>
<body>
<script>
    // Set the dimension of the canvas / graph
    var margin = { top: 30, right: 20, bottom: 30, left: 50 };
    var width = 600 - margin.left - margin.right;
    var height = 500 - margin.top - margin.bottom;

    // Add the svg canvas
    var svg = d3.select("body")
        .append("svg")
        .attr("width", width + margin.left + margin.right)
        .attr("height", height + margin.top + margin.bottom)
        .append("g")
        .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

    // Set the linear scale and the range for the axes
    var xRange = d3.scaleLinear().range([0, width]).domain([0, 10]);
    var yRange = d3.scaleLinear().range([height, 0]).domain([0, 10]);

    var line = d3.line()
        .x(d => xRange(d.x))
        .y(d => yRange(d.y))
        .curve(d3.curveLinear);

    var drag = d3.drag()
        .subject(function() { 
            var t = d3.select(this);
            return {x: t.attr("cx"), y: t.attr("cy")};
        })
        .on("drag", function (d) {
            var domain = yRange.domain();
            d.y = Math.max(domain[0], Math.min(yRange.invert(d3.event.y), domain[1]))
            d3.select(this).attr("cy", yRange(d.y));
            path.attr("d", line(points));
        });

    // Points dataset
    var radius = 6;
    var points = [{ x: 0, y: 0 }, { x: 5, y: 7 }, { x: 10, y: 10 }];

    // Add the X axis
    svg.append("g")
        .attr("transform", "translate(0," + height + ")")
        .call(d3.axisBottom(xRange));

    // Add the Y axis
    svg.append("g")
        .call(d3.axisLeft(yRange));

    // Add points to the svg
    var circles = svg.attr("class", "circle")
        .selectAll("circle")
        .data(points)
        .enter()
        .append("circle")
        .attr("cx", d => xRange(d.x))
        .attr("cy", d => yRange(d.y))
        .attr("r", radius)
        .attr("fill", "teal")
        .style("cursor", "pointer");

    // Add the path
    var path = svg.append("path")
        .attr("class", "line")
        .attr("d", line(points));

    drag(circles);
</script>
</body>
</html>