javascript - 如果用户单击 d3.js 中的圆形,如何防止拖动?
问题描述
我有 group 元素,它有 circle 和 rect 元素。用户可以拖动 group 元素,因此 rect 和 circle 元素都会移动。它工作正常。但是如果用户单击圆形元素,我需要防止拖动。JS小提琴
const x = 100;
var y = 100;
var grid = d3.select("#svg-area");
var g = grid.append("g")
.attr("transform", `translate(${x},${y})`)
.call(d3.drag()
.on("drag", function() {
var x1 = d3.event.x - 30;
var y1 = d3.event.y - 10;
d3.select(this).attr("transform", "translate(" +
(x1) + "," + (y1) + ")")
}));
newNode(g);
function newNode(g, text) {
var textWid = 100;
console.log('wid ', textWid);
g.append("rect")
.attr("class", "new-nodes")
.attr("x", '10')
.attr("y", '0')
.attr("rx", '6')
.attr("ry", '6')
.attr("width", textWid)
.attr("height", '35')
.style("fill", "#8c259f")
.style("stroke", "#222")
.style("cursor", "move");
g.append("circle")
.attr("class", "new-nodes")
.attr("cx", '10')
.attr("cy", '17')
.attr("r", '6')
.style("fill", "#dedede")
.style("stroke", "#b2b0b0")
.style("cursor", "pointer")
.on("click", function(d) {
/* d3.event.preventDefault();
d3.event.stopPropagation();
*/
});
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.13.0/d3.min.js"></script>
<svg id="svg-area" class="chart-area" width="500" height="500" pointer-events="all" style="cursor: crosshair; touch-action: none;">
</svg>
解决方案
最简单的方法(最接近您的代码的方法)是更改on("click"
为on("mousedown"
. 再次释放鼠标按钮时会注册“click”事件。在此之前清楚地注册了“mousedown”事件。而mousedown事件是触发“dragstart”的事件。
const x = 100;
var y = 100;
var grid = d3.select("#svg-area");
var g = grid.append("g")
.attr("transform", `translate(${x},${y})`)
.call(d3.drag()
.on("drag", function() {
var x1 = d3.event.x - 30;
var y1 = d3.event.y - 10;
d3.select(this).attr("transform", "translate(" +
(x1) + "," + (y1) + ")")
}));
newNode(g);
function newNode(g, text) {
var textWid = 100;
console.log('wid ', textWid);
g.append("rect")
.attr("class", "new-nodes")
.attr("x", '10')
.attr("y", '0')
.attr("rx", '6')
.attr("ry", '6')
.attr("width", textWid)
.attr("height", '35')
.style("fill", "#8c259f")
.style("stroke", "#222")
.style("cursor", "move");
g.append("circle")
.attr("class", "new-nodes")
.attr("cx", '10')
.attr("cy", '17')
.attr("r", '6')
.style("fill", "#dedede")
.style("stroke", "#b2b0b0")
.style("cursor", "pointer")
.on("mousedown", function(d) {
d3.event.preventDefault();
d3.event.stopPropagation();
});
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.13.0/d3.min.js"></script>
<svg id="svg-area" class="chart-area" width="500" height="500" pointer-events="all" style="cursor: crosshair; touch-action: none;">
</svg>
或者,您可以将事件移动到矩形并使用d3.drag().container
. 通常,d3.drag
计算事件与父元素之间的距离。现在,我们需要祖父母,因为父母(g
元素)是我们想要拖动的东西。
我还更改了g
元素以使用基准对象,因此您可以更轻松地移动它。
var grid = d3.select("#svg-area");
var g = grid.append("g")
.datum({
x: 100,
y: 100
})
.attr("transform", function(d) {
return `translate(${d.x},${d.y})`;
});
newNode(g);
function newNode(g, text) {
var textWid = 100;
console.log('wid ', textWid);
g.append("rect")
.attr("class", "new-nodes")
.attr("x", '10')
.attr("y", '0')
.attr("rx", '6')
.attr("ry", '6')
.attr("width", textWid)
.attr("height", '35')
.style("fill", "#8c259f")
.style("stroke", "#222")
.style("cursor", "move")
.call(d3.drag()
.container(grid.node())
.on("drag", function() {
d3.select(this.parentNode)
.attr("transform", function(d) {
d.x += d3.event.dx;
d.y += d3.event.dy;
return `translate(${d.x},${d.y})`;
});
}));
g.append("circle")
.attr("class", "new-nodes")
.attr("cx", '10')
.attr("cy", '17')
.attr("r", '6')
.style("fill", "#dedede")
.style("stroke", "#b2b0b0")
.style("cursor", "pointer");
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.13.0/d3.min.js"></script>
<svg id="svg-area" class="chart-area" width="500" height="500" pointer-events="all" style="cursor: crosshair; touch-action: none;">
</svg>
推荐阅读
- r - 如何使用ggplot在收益率曲线上绘制脉冲响应?
- python - 键绑定导致功能在启动时自动运行
- c# - ASP.Net Azure SignalR 错误无法 ping 服务器。服务器响应状态码 401,停止连接
- arrays - Rust 中的耦合数组
- node.js - 我们在 django 中是否有一些包或模块,通过它我们可以在编辑代码时看到 django 中 html 文件的实时更改?
- r - 基本 R 面板残差图标签
- python - ValueError:Flask 中闪存中解包的值太多(预期为 2)
- java - 使用 ActiveDirectoryLdapAuthenticationProvider 时检索 UserDetailsManager
- javascript - javascript提取两个标记之间的空格
- php - 如何在 php/html 中使用不同的变量重新启动循环