我正在处理一个包含 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>
您的drag
几乎不需要调整。
使用 https://stackoverflow.com/a/38650810/9938317 我更改了起始对象,因此我们开始在圆位置拖动。
然后我们需要反转该点的 y 值并将其填充到基准对象中。为了将阻力限制在轴域之外,我们首先将其钳制到域。
然后我们根据更新的points
数组更新path
。
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>