[英]D3 Differentiate between click and drag for an element which has a drag behavior
我無法使用D3.js v3成功區分綁定到兩者的元素上的click
事件和drag
事件。 下面的代碼中的圓圈被分配了拖動行為以及click
偵聽器。 在這里演示
var dragGroup = d3.behavior.drag()
.on('dragstart', function () {
console.log('Start Dragging Group');
})
.on('drag', function (d, i) {
d.x += d3.event.dx;
d.y += d3.event.dy;
d3.select(this).attr("transform", "translate(" + d.x + "," + d.y + ")");
});
var dragCircle = d3.behavior.drag()
.on('dragstart', function () {
d3.event.sourceEvent.stopPropagation();
d3.event.sourceEvent.preventDefault();
console.log('Start Dragging Circle');
})
.on('drag', function (d, i) {
d.cx += d3.event.dx;
d.cy += d3.event.dy;
d3.select(this).attr('cx', d.cx).attr('cy', d.cy);
});
var svg = d3.select('body').append('svg').attr('viewBox', '-50 -50 300 300');
var g = svg.selectAll('g').data([{
x: 10,
y: 10
}])
.enter().append('g').call(dragGroup);
g.append('rect').attr('width', 100).attr('height', 100);
g.selectAll('circle').data([{
cx: 90,
cy: 80
}]).enter()
.append('circle')
.attr('cx', function (d) {
return d.cx;
})
.attr('cy', function (d) {
return d.cy;
})
.attr('r', 30)
.call(dragCircle)
.on('click', function () {
console.log('clicked circle');
});
每當我單擊示例中的圓圈時,我都會讓控制台記錄drag
事件以及click
事件。 拖動時我也會得到相同的行為,首先記錄drag
事件,然后在mouseup
上記錄click
事件。
分別處理這些事件的正確方法是什么?
用例是嘗試在樹布局中處理節點單擊和節點拖放。
缺少的關鍵位是檢查是否已阻止事件的默認行為。 也就是說,有一個匹配同級d3.event.preventDefault()
- d3.event.defaultPrevented
。 您需要在click
處理程序中檢查這一點,以查看是否正在進行任何拖動操作。
另見這個問題的答案。
您可以區分click
和dragstart
,但很難區分mousdown
和dragstart
。
當您開始拖動操作時,將觸發dragstart
,這意味着當您執行mousedown
。 這就是為什么。 無論何時click
,都會triggered
dragstart
。 ( click
是mousedown
+ mouseup
)。
因此, 防止點擊被觸發應該有效 。 在你的代碼中,你應該像Lars Kotthoff暗示的那樣添加preventDefault。 但是不要把它放在dragstart函數中:
var dragCircle = d3.behavior.drag()
.on('dragstart', function () {
d3.event.sourceEvent.stopPropagation();
d3.event.sourceEvent.preventDefault(); <-- Remove This
console.log('Start Dragging Circle');
})
並將其添加在正確的地方(在點擊功能),並將其與D3寫正確(d3.event。defaultPrevented)
g.selectAll('circle').data([{
cx: 90,
cy: 80
}]).enter()
.append('circle')
.attr('cx', function (d) {
return d.cx
})
.attr('cy', function (d) {
return d.cy
})
.attr('r', 30)
.call(dragCircle)
.on('click', click);
function click(d) {
if (d3.event.defaultPrevented) return; <-- Add d3.event.defaultPrevented
console.log('clicked');
}
請參閱更新版本 。 現在,拖動時,不再觸發click
。
請記住,單擊時,仍會觸發dragstart
。 (但不是drag
)
d3.event.sourceEvent.preventDefault()
不能按預期工作,或者它不一致。
我遇到了這個問題,為了區分這兩個事件,我在onDrag
事件中使用了一個布爾值isDragged
。 因此,如果設置了此值,則在對象上執行drag
事件(如果不是),則執行click
事件。 正常點擊對象dragend
觸發其dragstart
和dragend
事件,但不會onDrag
事件。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.