D3 Различия между щелчком и перетаскиванием для элемента, который имеет поведение перетаскивания
Я не могу успешно провести различие между событием click
и событием drag
для элемента, связанного с использованием D3.js v3. Кругу в приведенном ниже коде присваивается поведение перетаскивания, а также прослушиватель 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
.
Каков правильный способ обработки этих событий отдельно?
Вариант использования - попытка обработать node -click и node -drag/drop в макете дерева.
Ответы
Ответ 1
Недопустимый бит ключа - это проверка того, было ли предотвращено поведение события по умолчанию. То есть, подходящий брат к d3.event.preventDefault()
- d3.event.defaultPrevented
. Вы должны проверить это в своем обработчике click
, чтобы узнать, не происходит ли какое-либо действие перетаскивания.
См. также ответ на этот вопрос.
Ответ 2
Вы можете различать a click
и a dragstart
, но сложнее провести различие между mousdown
и a dragstart
.
dragstart
будет запущен, когда вы начнете действие перетаскивания, что означает, когда вы выполните mousedown
. Вот почему. click
, dragstart
будет triggered
. (a click
является mousedown
+ mouseup
).
Значит предотвращение срабатывания клика должно работать. В вашем коде вы должны добавить предупреждение, как указывал Ларс Котхофф. Но не ставьте его в функцию 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
)