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>
解决方案
你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>
推荐阅读
- terraform - 使用 terraform-cloudflare 提供程序的 Cloudflare 页面规则不会更新页面规则
- javascript - addEventListener 输入键码不起作用
- python-3.x - 矩阵乘法 Python
- xcode - 无法在与 Xcode 断开连接的设备上运行我的应用程序
- c# - Analyzer + Code Fix 不生成选项
- python - 检查输入是否在 url 列表中
- node.js - 如何实时更新api?
- python - Pandas --Groupby 多列返回最后一个值
- wordpress - 在 REST API wordpress 中显示类别图标
- python - binascii.crc32 中的 CRC32 输出可变校验和长度:8-9-10 位