Это хитрый, потому что если вы связать событие перетаскивания к 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>
Это работает! Большое спасибо. Но если я хочу привязать кисть к сотням элементов в группе и отключить событие только на нескольких элементах. Кажется, что я должен использовать for-loop для выбора элементов, которые я хочу называть кистью. Это не похоже на d3-стиль. :( –
вам не нужен цикл for, просто используйте выбор d3 и вызовите '.call (drag)', и все должно быть в порядке. –