2015-03-25 2 views
1

У меня есть перетаскиваемая группа, и один элемент в этой группе вызвал событие click. Теперь я хочу удалить событие перетаскивания для этого элемента. См http://jsfiddle.net/gLvyouct/1/Как удалить событие перетаскивания на один элемент в группе перетаскивания?

Я пробовал эти методы:

  • Добавить circle.call(drag).on(".drag", null);

    Не работает, и я не знаю почему.

  • Вызывайте перетаскивать события на прямоугольниках

    Повлияет беглость событий перетаскивания. Элементы дрожат при перетаскивании.

  • В определении поведения сопротивления if (d3.event.sourceEvent.target.nodeName == "circle") return;

    Не работает. Группа продолжает двигаться, когда ваша мышь находится на краю круга.

ответ

0

Это хитрый, потому что если вы связать событие перетаскивания к rect, а затем переместить g что прямоугольник находится в расчетные dx и dy значения в d3.event объекта будет перепутались после каждого события, поскольку эти расчетные значения были преобразованы в локальную систему координат элемента, к которой привязано поведение сопротивления. Итак, мы можем сделать что-то подобное себе, чтобы обойти это. Трюк здесь - это знание того, что нам действительно нужно выяснить изменения в позиции мыши во время действия перетаскивания в позиции x и y. И что d3 делает их доступными в свойстве sourceEvent объекта d3.event.

Поэтому использовать лежащую в основе sourceEvent в d3.event объекта, чтобы получить clientX и clientY положение и просто вычислить разницу между последними значениями и текущими значениями, которые расскажут вам, как далеко дополнительные вам нужно translate на g элемент. Вам также необходимо инициализировать значения, которые вы сравниваете, чтобы вы не получали случайный переход в начале. К счастью, мы можем использовать событие dragstart, чтобы сделать именно это.

Как только мы это выясним, мы сможем привязать обработчик drag к rect, и мы должны быть хорошими.

Вот пример того, что я описал.

var g = d3.select("#mysvg").append("g"); 
 
var rect = g.append("rect").attr("height", 100).attr("width", 100); 
 
var circle = g.append("circle").attr("cx", 200).attr("cy", 200).attr("r", 50).attr("fill", "black"); 
 
var transX = 0, transY = 0; 
 
var lastX = 0, lastY = 0; 
 

 
var drag = d3.behavior.drag().on("drag", function() { 
 
    transX += d3.event.sourceEvent.clientX - lastX; 
 
    transY += d3.event.sourceEvent.clientY - lastY; 
 
    g.attr("transform", "translate(" + transX + "," + transY + ")"); 
 
    lastX = d3.event.sourceEvent.clientX; 
 
    lastY = d3.event.sourceEvent.clientY; 
 
}).on("dragstart", function() { 
 
    lastX = d3.event.sourceEvent.clientX; 
 
    lastY = d3.event.sourceEvent.clientY; 
 
}); 
 
rect.call(drag); 
 

 
circle.on("click", function() { 
 
    var now_color = d3.select(this).attr("fill"); 
 
    if (now_color == "black") 
 
     d3.select(this).attr("fill", "green"); 
 
    else 
 
     d3.select(this).attr("fill", "black"); 
 
}); 
 

 
//circle.call(drag).on(".drag", null);
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script> 
 
<svg id="mysvg" height="800" width="800"></svg>

+0

Это работает! Большое спасибо. Но если я хочу привязать кисть к сотням элементов в группе и отключить событие только на нескольких элементах. Кажется, что я должен использовать for-loop для выбора элементов, которые я хочу называть кистью. Это не похоже на d3-стиль. :( –

+0

вам не нужен цикл for, просто используйте выбор d3 и вызовите '.call (drag)', и все должно быть в порядке. –

Смежные вопросы