我正在尝试在d3js中绘制一个UI,其中我有一个顶部面板,我应该能够将drag
和drop
元素添加到一个组并复制它们。我已经实现了这个目标,但我的代码中存在一个错误。我真正想要做的是,拖动circle
并复制它。但是,当我单击顶部面板中的circle
时,它会自动触发拖动事件并自行复制。我怎么能阻止这种行为?
<svg height="600" width="600" style="background: black">
<g>
<rect x="0" y="0" , width="600" height="40" style="fill:gold;"></rect>
<circle id='drag' cx="15" cy="20" init-cx="15" init-cy="20" r="10"
style="stroke: white; stroke-width: 2px; fill:blue"/>
</g>
<g id="playground">
<g>
<circle id='top' cx="180" cy="120" r="30" style="stroke: white; stroke-width: 2px; fill:white"/>
</g>
<g>
<circle id='top' cx="200" cy="220" r="30" style="stroke: white; stroke-width: 2px; fill:white"/>
</g>
<g>
<circle id='top' cx="320" cy="150" r="50" style="stroke: white; stroke-width: 2px; fill:white"/>
</g>
</g>
</svg>
<script>
$(document).ready(function () {
var move = d3.behavior.drag()
.on('drag', function () {
console.log('dragging');
var curr = d3.select(this)
.attr({
cx: d3.mouse(this)[0],
cy: d3.mouse(this)[1]
})
})
.on('dragend', function () {
var curr = d3.select(this);
d3.select('#playground')
.append('circle')
.attr({
cx : curr.attr('cx'),
cy : curr.attr('cy'),
r : curr.attr('r')
})
.style({
fill : 'white',
stroke : 'red',
'stroke-width' : '2px'
})
;
curr.attr({
cx : curr.attr('init-cx'),
cy : curr.attr('init-cx')
});
})
;
d3.select('#drag').call(move);
});
</script>
这是我工作的小提琴。 https://jsfiddle.net/fawzan/my2g724L/
答案 0 :(得分:1)
你只需要检查拖拽结束事件的目标是否是同一个圆圈,只有当它们不匹配时才复制圆圈。
.on('dragend', function() {
if (d3.event.sourceEvent.target != this) {
var curr = d3.select(this);
d3.select('#playground')
.append('circle')
.attr({
cx: curr.attr('cx'),
cy: curr.attr('cy'),
r: curr.attr('r')
})
.style({
fill: 'white',
stroke: 'red',
'stroke-width': '2px'
});
curr.attr({
cx: curr.attr('init-cx'),
cy: curr.attr('init-cx')
});
}
});
var move = d3.behavior.drag()
.on('drag', function() {
console.log('dragging');
console.log(this)
console.log(this)
var curr = d3.select(this)
.attr({
cx: d3.mouse(this)[0],
cy: d3.mouse(this)[1]
})
})
.on('dragend', function() {
if (d3.event.sourceEvent.target != this) {
var curr = d3.select(this);
d3.select('#playground')
.append('circle')
.attr({
cx: curr.attr('cx'),
cy: curr.attr('cy'),
r: curr.attr('r')
})
.style({
fill: 'white',
stroke: 'red',
'stroke-width': '2px'
});
curr.attr({
cx: curr.attr('init-cx'),
cy: curr.attr('init-cx')
});
}
});
d3.select('#drag').call(move);
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<svg height="600" width="600" style="background: black">
<g>
<rect x="0" y="0" , width="600" height="40" style="fill:gold;"></rect>
<circle id='drag' cx="15" cy="20" init-cx="15" init-cy="20" r="10" style="stroke: white; stroke-width: 2px; fill:blue" />
</g>
<g id="playground">
<g>
<circle id='top' cx="180" cy="120" r="30" style="stroke: white; stroke-width: 2px; fill:white" />
</g>
<g>
<circle id='top' cx="200" cy="220" r="30" style="stroke: white; stroke-width: 2px; fill:white" />
</g>
<g>
<circle id='top' cx="320" cy="150" r="50" style="stroke: white; stroke-width: 2px; fill:white" />
</g>
</g>
</svg>
&#13;
答案 1 :(得分:1)
希望这对你有用, 看一看。 我在'dragend'中添加了一些代码,就是在这里我决定是否通过使用init-cx和init-cy之类的circle属性来创建/附加一个圆圈到游乐场。我添加的代码是
var initX = (curr.attr('init-cx')*1);
var currX = (curr.attr('cx')*1);
var initY = (curr.attr('init-cy')*1);
var currY = (curr.attr('cy')*1);
if(((currX) > (initX+20)) || ((currY) > (initY+20))){
//Here code to append a circle to playground
}
:d
答案 2 :(得分:0)
点击时看到你的curr.attr('cx')
偏移返回15。所以你可以通过在dragend方法上添加条件来阻止默认操作:
if(curr.attr('cx')==15){
return false;
}
更通用:
var isClicked = false;
var move = d3.behavior.drag()
.on('dragstart', function() {
isClicked = true;
})
.on('drag', function() {
isClicked = false;
var curr = d3.select(this)
.attr({
cx: d3.mouse(this)[0],
cy: d3.mouse(this)[1]
})
})
.on('dragend', function() {
var curr = d3.select(this);
if (!isClicked) {
d3.select('#playground')
.append('circle')
.attr({
cx: curr.attr('cx'),
cy: curr.attr('cy'),
r: curr.attr('r')
})
.style({
fill: 'white',
stroke: 'red',
'stroke-width': '2px'
});
}
curr.attr({
cx: curr.attr('init-cx'),
cy: curr.attr('init-cx')
});
});
d3.select('#drag').call(move);
d3.select('#drag').on('click', click);
function click(d) {
isClicked = true;
}
结帐Fiddle:
答案 3 :(得分:0)
使用布尔值监视拖动是否已启动。这样,您可以停止Dragend功能。
$(document).ready(function () {
var isDragged = false;
var move = d3.behavior.drag()
.on('drag', function () {
console.log('dragging');
isDragged = true;
var curr = d3.select(this)
.attr({
cx: d3.mouse(this)[0],
cy: d3.mouse(this)[1]
})
})
.on('dragend', function () {
if (!isDragged) return;
isDragged = false;
var curr = d3.select(this);
d3.select('#playground')
.append('circle')
.attr({
cx : curr.attr('cx'),
cy : curr.attr('cy'),
r : curr.attr('r')
})
.style({
fill : 'white',
stroke : 'red',
'stroke-width' : '2px'
})
;
curr.attr({
cx : curr.attr('init-cx'),
cy : curr.attr('init-cx')
});
})
;
d3.select('#drag').call(move);
});
答案 4 :(得分:0)
对于 D3 v4(可能适用于 v5 和 v6),您可以在 dragged
事件期间确定节点的位置,并查看是否与其原始位置不同。假设它没有,alphaTarget
永远不会被调用。
例如:
function dragstarted(d) {
// if (!d3.event.active) simulation.alphaTarget(0.2).restart();
d.fx = d.x;
d.fy = d.y;
}
function dragged(d) {
if (d3.event.active && (d.fy != d3.event.y || d.fx != d3.event.x)) {
simulation.alphaTarget(0.5).restart();
}
d.fx = d3.event.x;
d.fy = d3.event.y;
}
function dragended(d) {
if (!d3.event.active) simulation.alphaTarget(0);
d.fx = null;
d.fy = null;
}