javascript - 我可以在 d3.js 中使用 drag.container 来限制拖动区域吗?
问题描述
我试图理解 d3.drag() 但我无法掌握drag.container()部分中的内容,所以我在这里寻求帮助。
这是我理解的方式:如果我添加容器功能,那么我可以限制我可以拖动的区域。如果解释正确,那么我该如何使用它?
例如,在下面的代码片段中,我创建了一个可以拖动的圆圈。但我只想限制白色圆圈内的拖动区域。我可以使用 drag.container() 吗?
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="https://d3js.org/d3.v6.min.js"></script>
<style>
</style>
</head>
<body>
<script>
const svg = d3.select("body").append("svg").attr("width", "600").attr("height", "500").style("background", "lightblue");
// Can I use this circle as the container?
const circleAsContainer = svg.append("circle").attr("cx", "180").attr("cy", "200").attr("r", "120").attr("fill", "white")
const circle = svg.append("circle").attr("cx", "120").attr("cy", "150").attr("r", "30").attr("fill", "orange").call(d3.drag()
.on("start", (event, d) => circle.attr("stroke", "black").attr("stroke-width", "4"))
.on("drag", (event, d) => circle.attr("cx", d => event.x).attr("cy", d => event.y))
.on("end", (event, d) => circle.attr("stroke", "none"))
);
</script>
</body>
</html>
解决方案
这是我的代码。试试把蓝圈移到红圈外面~
.active {
stroke: #000;
stroke-width: 2px;
}
<script src="https://d3js.org/d3.v4.min.js"></script>
<svg width="1000" height="500" style="border: 1px solid black">
<circle cx="250" cy="250" r="200" style="fill:none;stroke:#FF7F7F;stroke-width:16px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;z-index: 1;"/>
<circle cx="750" cy="250" r="200" style="fill:none;stroke:#FF7F7F;stroke-width:16px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;z-index: 1;"/>
</svg>
<script>
var svg = d3.select("svg"),
width = +svg.attr("width"),
height = +svg.attr("height"),
radius = 32;
var circles = [{},{},
// dcx: default_center_X_coordinate
{dcx: 250, dcy: 250, color: '#1f77b4', id: 0},
{dcx: 750, dcy: 250, color: '#aec7e8', id: 1}];
svg.selectAll("circle")
.data(circles)
.enter().append("circle")
.attr("cx", function(d) { return d.dcx; })
.attr("cy", function(d) { return d.dcy; })
.attr("dcx", function(d) { return d.dcx; })
.attr("dcy", function(d) { return d.dcy; })
.attr("r", radius)
.attr("id", function(d) { return d.id; })
.style("fill", function(d, i) { return d.color; })
.call(d3.drag()
.on("start", dragstarted)
.on("drag", dragged)
.on("end", dragended));
function dragstarted(d) {
d3.select(this)
.raise()
.classed("active", true);
}
function keepInCircle(dcx, dcy, x, y, r) {
const dx = x - dcx,
dy = y - dcy,
dist = Math.sqrt(dx * dx + dy * dy)
return (dist>r) ? { x:dcx+dx/dist*r, y:dcy+dy/dist*r } : {x:x, y:y}
}
function dragged(d) {
//console.log(d.id);
var obj = keepInCircle(d.dcx, d.dcy, d3.event.x, d3.event.y, 200)
d3.select(this)
.attr("cx", obj.x)
.attr("cy", obj.y);
}
function dragended(d) {
d3.select(this)
.attr("cx", d.dcx)
.attr("cy", d.dcy)
.classed("active", false);
}
</script>
推荐阅读
- azure - ADF 管道成本
- json - 在快速解析 JSON 时,无法将类型“[String:Any]”的值转换为预期的参数类型“[String:String]”
- c++ - 在数组中查找重复项 - 语法说明
- python - pickle.PicklingError: Can't pickle: it's not the same object as
- riscv - 为什么在 RISC-V ISA 中永远无法访问地址空间中的空白位置?
- oracle - 尝试在 Oracle Applications R12 上将字段设置为必填项
- pandas - for 循环创建数据帧并连接
- blazor-server-side - 当用户首次登录时,Blazor 服务器应用程序是否有我可以处理的事件?
- azure - 无法使用本地登录在自定义策略中重新运行访问令牌
- prisma - 如何使用 Prisma 和 createMany 播种 mssql 数据库