首页 > 解决方案 > 图形中的点移动时更新路径

问题描述

我正在处理一个包含 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>

标签: d3.js

解决方案


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>


推荐阅读