簡體   English   中英

D3區分具有拖動行為的元素的單擊和拖動

[英]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處理程序中檢查這一點,以查看是否正在進行任何拖動操作。

另見這個問題的答案。

您可以區分clickdragstart ,但很難區分mousdowndragstart

當您開始拖動操作時,將觸發dragstart ,這意味着當您執行mousedown 這就是為什么。 無論何時click ,都會triggered dragstart clickmousedown + 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觸發其dragstartdragend事件,但不會onDrag事件。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM