Перетаскивание «Заикание» при использовании d3.behavior.drag () и преобразование

18

Я пытаюсь использовать событие d3.js d3.behavior.drag() drag , чтобы обновить мою модель данных (без немедленной установки позиции элемента), а затем запустить функцию «рисования», чтобы обновить все элементы на основе обновленной модели. Кроме того, я использую translate transform для содержащего элемента группы, чтобы переместить все элементы, связанные с перетаскиваемым объектом (я удалил дополнительные элементы из примера, приведенного ниже). Это приводит к тому, что перетаскиваемые элементы заикаются при перетаскивании, что ухудшается при более быстром перетаскивании.

См. этот урезанный пример для jsFiddle .

Вот код примера:

blocks = [
  { x: 0, y: 0 }
];

drag = d3.behavior.drag()
  .origin(Object)
  .on("drag", function(d) {
    d.x = d3.event.x;
    d.y = d3.event.y;
    draw();
  });

svg = d3.select("body")
  .append("svg:svg")
  .attr("width", 600)
  .attr("height", 600);

function draw() {
  g = svg.selectAll("g")
    .data(blocks);

  gEnter = g.enter().append("g");

  g.attr("transform", function(d) { return "translate("+d.x+","+d.y+")"; });

  gEnter.append("rect")
    .attr("height", 100)
    .attr("width", 100)
    .call(drag);
}

draw()​;
    
задан tlrobinson 26.10.2012 в 00:51
источник

3 ответа

34

Вы вызываете drag для элемента rect , но вы трансформируете его родителя: элемент g .

Проблема заключается в том, что компонент перетаскивания использует местоположение мыши относительно родительского элемента для определения новых d3.event.x и d3.event.y . Таким образом, если вы перемещаете (то есть transform ) родительский объект, пока пользователь перетаскивает его, все будет неправильно.

Решение состоит в том, чтобы вызвать drag для того же элемента, который вы перемещаете; в этом случае элемент g :

function draw() {
  g = svg.selectAll("g")
    .data(blocks);

  gEnter = g.enter().append("g")
    .call(drag);

  g.attr("transform", function(d) { return "translate("+d.x+","+d.y+")"; });

  gEnter.append("rect")
    .attr("height", 100)
    .attr("width", 100);
}

См. исправленную скрипку: Ссылка

    
ответ дан nautat 26.10.2012 в 03:47
  • В версии 4 D3 есть функция контейнера, которая позволяет установить другой узел для определения координат. –  user2393229 23.01.2018 в 20:28
5

У меня была та же проблема, что и у Дарвина. Обработчик перетаскивания находится на дочернем объекте, к которому прикреплены данные D3, но преобразование необходимо применить к родительской группе (не к d3).

Я решил это, установив функцию origin для возврата x: 0, y: 0, а затем используя значение x в событии, а не dx.

например

var drag = d3.behavior.drag()
    .origin(function(d,i) { return {x:0, y:0}; })
    .on("drag", function (d) {  movePosition(d3.event.x);   });
    
ответ дан avowkind 25.05.2013 в 01:11
3

Nautat предоставил хорошее решение для вашего дела.

Мой случай немного сложнее. Мои данные связаны ниже g-узла, который я хочу преобразовать. В этом случае я не могу просто переместить .call (перетащить) на g-уровень.

Я отправил запрос на извлечение, чтобы настроить базовое пространство координат: Ссылка

    
ответ дан Antonin Hildebrand 05.02.2013 в 21:16