簡體   English   中英

d3點擊拖動事件嵌套

[英]d3 click and drag event nesting

我在 ag 元素中嵌套了很多元素,如下所示:

<g>
    <rect></rect>
    <text></text>
    ...
</g>

然而,有一些矩形我希望能夠擁有它們自己的拖動事件。 問題是,當您將內容放入 ag 標簽時,它的大小會擴展以包含這些標簽。 因此,即使我可以分配事件,也無法觸發它們,因為 g 標記的事件在某種程度上更重要,即使 rect 位於它之上。

你們知道有某種解決方法嗎?

編輯:這是一個完整的簡單案例 g 內的一個矩形和一個圓。 g 是可拖動的,圓圈也應該是可拖動的,但不是。

var gDragBehav = d3.behavior.drag()
    .on('drag', gDragDrag)

function gDragDrag(d,i) {
    d.x += d3.event.dx;
    d.y += d3.event.dy;
    d3.select(this)
        .attr('x', d.x)
        .attr('y', d.y)
        .attr("transform", "translate(" + d.x + "," + d.y + ")");
}

var circleDragBehav = d3.behavior.drag()
    .on('drag', circleDragDrag);

function circleDragDrag(d,i) {
    console.log('dragging a circle')
    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')

var g = svg.selectAll('g').data([{x: 10, y:10}])
    .enter().append('g').call( gDragBehav )

g.append( 'rect' ).attr('width', 100 ).attr('height', 100 )

g.selectAll( 'circle' ).data([{cx: 0, cy:0}])
    .enter().append( 'circle' )
    .attr('cx', function(d) { return d.cx } ).attr('cy', function(d) { return d.cy } )
    .attr('r', 40 )
    .call( circleDragBehav )

編輯:這是一些代碼

var group = this.d3svg.selectAll('g' + '.' + this.className)
  .attr('x', this.drawFuncs['x'] )
  .attr('y', this.drawFuncs['y'] )
  .attr("transform", this.drawFuncs['translate'] )
  .attr('class', this.className )
  .call(gDragBehav)
  .on( 'click', blockClickMenu )

ports = ['AtomicPort']
for ( port in ports ) {  
  drawPort.call( this, group, ports[port] )
}

function drawPort( d3svg, portName, redraw ) {
  d3svg.selectAll('rect.' + portName)
    .data( function(d) { return d.ports[ portName ] } )
    .enter().append('rect')
    .attr('x', this.drawFuncs['x'] )
    .attr('y', this.drawFuncs['y'] )
    .attr('width', this.drawFuncs['width'] )
    .attr('height', this.drawFuncs['height'] )
    .attr('class', portName )
    .call(portDragBehav)

  var portDragBehav = d3.behavior.drag()
    .on('drag', portDragDrag);

  function portDragDrag(d,i) {
    d.x += d3.event.dx;
    d.y += d3.event.dy;
    d3.select(this)
      .attr('x', d.x)
      .attr('y', d.y)
    d3.event.stopPropagation();
  }

  var gDragBehav = d3.behavior.drag()
    .on('dragstart', gDragStart)

  function gDragDrag(d,i) {
    d.x += d3.event.dx;
    d.y += d3.event.dy;
    d3.select(this)
      .attr('x', d.x)
      .attr('y', d.y)
      .attr("transform", "translate(" + d.x + "," + d.y + ")");
    d3.event.stopPropagation(); //Uncaught TypeError: Object #<Object> has no method 'stopPropagation'
  }

SVG <g>元素沒有大小或面積; 它是其所有后代的透明容器,並且不能攔截其他元素的事件(除非您要添加一個要在“捕獲階段”期間觸發的事件偵聽器)。

作為父元素,事件會向上冒泡; 您可能看到的是,無論您使用什么事件來觸發<rect>上的拖動開始(鼠標按下?),也會冒泡到<g>並開始並發拖動

要解決此問題,您需要阻止事件冒泡。 <rect>上的鼠標按下(或其他)的事件處理程序中添加:

function startDrag(evt){
  // whatever your code is here
  evt.stopPropagation();
}

如果沒有您的實際代碼(或者更好的是,精簡的測試用例),則很難確定或進一步幫助您。


編輯這是您的簡單示例的工作版本: http://jsfiddle.net/ZrCQE/2/

具體來說,顯然d3.event不是事件本身,而是帶有引用實際事件的sourceEvent屬性的 object。

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();
    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);​

我有類似的問題 ( http://jsfiddle.net/j8RZN/1/ ),除了建議的解決方法似乎沒有幫助。

userBox.data([userBox]).call(d3.behavior.drag() //makes the box to move
//titleBox.data([userBox]).call(d3.behavior.drag()  //does not make the box move
.on("dragstart", function() {})
.on("drag", function(d, i) {
console.log('box being dragged');
d.attr("transform", "translate(" + (d3.event.x) +  "," + (d3.event.y) + ")");
})
.on("dragend", function() {}));

circleDrag.call(d3.behavior.drag()
.on("dragstart", function() {})
.on("drag", function(d, i) {
 d3.event.sourceEvent.stopPropagation();
 console.log('small rectangle being dragged');
})
.on("dragend", function() {}));

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM