Остановить событие dragmove программно в D3 v5 - PullRequest
2 голосов
/ 20 сентября 2019

В проекте Vue / D3 мне нужно установить некоторые ограничения на перемещение некоторых перетаскиваемых элементов.

Это выдержка из обработчика dragmove:

dragmove: function(d, i, n) {     
    // Stop if the node crosses a border
    if (parseInt(n[i].getAttribute('x')) > 200) {
        this.drag.dragend(); 
    }
}

this.drag.dragend(); взято из старого ответа на Stackoverflow .К сожалению, он не работает в D3 v5 (this.drag.dragend is not a function).

Это моя drag переменная:

drag: d3.drag()
        .on('drag', this.dragmove)
        .on('end', this.dragended),

Есть ли способ обновить мой код для работы с другимипоследние версии D3?

1 Ответ

0 голосов
/ 20 сентября 2019

Вы можете использовать d3.event.on для временного переопределения прослушивателей событий.Таким образом, чтобы программно прервать перетаскивание во время самого события перетаскивания, мы можем использовать:

d3.event.on("drag", null)
d3.event.on("end", null)

Это временно удаляет функции, назначенные каждому слушателю события.Вы заметите, что я тоже удаляю событие завершения - в противном случае оно продолжит прослушивание мыши вверх, независимо от того, назначена ли функция прослушивателю события «перетаскивания».

Эта функция описана в d3-dragevent.on:

event.on (typenames, [listener])

Эквивалентно drag.on, но применяется только к текущему жесту перетаскивания.Перед началом жеста перетаскивания создается копия текущего слушателя события перетаскивания.Эта копия привязана к текущему жесту перетаскивания и изменена с помощью event.on.Это полезно для временных слушателей, которые получают события только для текущего жеста перетаскивания.( source )

В приведенном ниже примере события перетаскивания временно удаляются из круга, когда он попадает в линию.Пользовательское событие отправляется, чтобы указать, что перетаскивание было программно прервано.Все события записываются в журнал - это означает, что события завершения, перетаскивания и прерывания работают должным образом:

var svg = d3.select("svg");

var drag = d3.drag()
  .on("drag", function() {
    log(); // to log events as they are triggered.
	
    var selection = d3.select(this);
      
    // Update the circle as normal (but don't let cx exceed the line visually):
    selection.attr("cx", d3.event.x > 300 ? 300 : d3.event.x)
      .attr("cy", d3.event.y);
	  
      // If event.x > 300, interrupt drag:
    if(d3.event.x > 300) {
      
    // Disable the drag events temporarily
      d3.event.on("drag", null)
      d3.event.on("end", null) 

      // Optionally trigger some alternative event 
      selection.dispatch("interrupted");
    }
	
  })
  .on("end", function() {
    log(); 
  })

var circle = svg.select("circle")
  .call(drag)
  .on("interrupted", function() {
    d3.select(this)
      .transition()
      .attr("fill","orange")
      .attr("cx",250)
      .transition()
      .attr("fill","steelblue");
 
    log();
  })	
  

function log() {
	console.log(d3.event.type);
}
.as-console-wrapper { max-height: 40% !important; }
circle { cursor: pointer ; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<svg width="500" height="300">
	<circle cx="100" cy="50" fill="steelblue" r="10"></circle>
	<line x1="305" x2="305" y1="0" y2="400" stroke-width="1" stroke="black"></line>
</svg>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...