d3js阻止了对点击事件的拖拽

时间:2015-11-25 04:59:47

标签: javascript d3.js svg

我正在尝试在d3js中绘制一个UI,其中我有一个顶部面板,我应该能够将dragdrop元素添加到一个组并复制它们。我已经实现了这个目标,但我的代码中存在一个错误。我真正想要做的是,拖动circle并复制它。但是,当我单击顶部面板中的circle时,它会自动触发拖动事件并自行复制。我怎么能阻止这种行为?

<svg height="600" width="600" style="background: black">

    <g>
        <rect x="0" y="0" , width="600" height="40" style="fill:gold;"></rect>
        <circle id='drag' cx="15" cy="20" init-cx="15" init-cy="20" r="10"
                style="stroke: white; stroke-width: 2px; fill:blue"/>

    </g>

    <g id="playground">
        <g>
            <circle id='top' cx="180" cy="120" r="30" style="stroke: white; stroke-width: 2px; fill:white"/>
        </g>
        <g>
            <circle id='top' cx="200" cy="220" r="30" style="stroke: white; stroke-width: 2px; fill:white"/>
        </g>
        <g>
            <circle id='top' cx="320" cy="150" r="50" style="stroke: white; stroke-width: 2px; fill:white"/>
        </g>
    </g>
</svg>

<script>

    $(document).ready(function () {


        var move = d3.behavior.drag()
            .on('drag', function () {

                console.log('dragging');

                var curr = d3.select(this)
                    .attr({
                        cx: d3.mouse(this)[0],
                        cy: d3.mouse(this)[1]
                    })


            })
            .on('dragend', function () {

                var curr = d3.select(this);

                d3.select('#playground')
                    .append('circle')
                    .attr({
                        cx : curr.attr('cx'),
                        cy : curr.attr('cy'),
                        r : curr.attr('r')
                    })
                    .style({
                        fill : 'white',
                        stroke : 'red',
                        'stroke-width' : '2px'
                    })
                ;

                curr.attr({
                    cx : curr.attr('init-cx'),
                    cy : curr.attr('init-cx')
                });
            })
            ;


        d3.select('#drag').call(move);


    });


</script>

这是我工作的小提琴。 https://jsfiddle.net/fawzan/my2g724L/

5 个答案:

答案 0 :(得分:1)

你只需要检查拖拽结束事件的目标是否是同一个圆圈,只有当它们不匹配时才复制圆圈。

.on('dragend', function() {
    if (d3.event.sourceEvent.target != this) {
      var curr = d3.select(this);

      d3.select('#playground')
        .append('circle')
        .attr({
          cx: curr.attr('cx'),
          cy: curr.attr('cy'),
          r: curr.attr('r')
        })
        .style({
          fill: 'white',
          stroke: 'red',
          'stroke-width': '2px'
        });

      curr.attr({
        cx: curr.attr('init-cx'),
        cy: curr.attr('init-cx')
      });
    }
});

&#13;
&#13;
var move = d3.behavior.drag()
  .on('drag', function() {

    console.log('dragging');
    console.log(this)
    console.log(this)

    var curr = d3.select(this)
      .attr({
        cx: d3.mouse(this)[0],
        cy: d3.mouse(this)[1]
      })


  })
  .on('dragend', function() {
    if (d3.event.sourceEvent.target != this) {
      var curr = d3.select(this);

      d3.select('#playground')
        .append('circle')
        .attr({
          cx: curr.attr('cx'),
          cy: curr.attr('cy'),
          r: curr.attr('r')
        })
        .style({
          fill: 'white',
          stroke: 'red',
          'stroke-width': '2px'
        });

      curr.attr({
        cx: curr.attr('init-cx'),
        cy: curr.attr('init-cx')
      });
    }
  });


d3.select('#drag').call(move);
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<svg height="600" width="600" style="background: black">

  <g>
    <rect x="0" y="0" , width="600" height="40" style="fill:gold;"></rect>
    <circle id='drag' cx="15" cy="20" init-cx="15" init-cy="20" r="10" style="stroke: white; stroke-width: 2px; fill:blue" />

  </g>

  <g id="playground">
    <g>
      <circle id='top' cx="180" cy="120" r="30" style="stroke: white; stroke-width: 2px; fill:white" />
    </g>
    <g>
      <circle id='top' cx="200" cy="220" r="30" style="stroke: white; stroke-width: 2px; fill:white" />
    </g>
    <g>
      <circle id='top' cx="320" cy="150" r="50" style="stroke: white; stroke-width: 2px; fill:white" />
    </g>
  </g>
</svg>
&#13;
&#13;
&#13;

答案 1 :(得分:1)

希望这对你有用, 看一看。 我在'dragend'中添加了一些代码,就是在这里我决定是否通过使用init-cx和init-cy之类的circle属性来创建/附加一个圆圈到游乐场。我添加的代码是

var initX = (curr.attr('init-cx')*1);
var currX = (curr.attr('cx')*1);
var initY = (curr.attr('init-cy')*1);
var currY = (curr.attr('cy')*1);                  
if(((currX) > (initX+20)) || ((currY) > (initY+20))){
//Here code to append a circle to playground
}

Fiddle

:d

答案 2 :(得分:0)

点击时看到你的curr.attr('cx')偏移返回15。所以你可以通过在dragend方法上添加条件来阻止默认操作:

if(curr.attr('cx')==15){
   return false;
}

更通用:

var isClicked = false;
var move = d3.behavior.drag()
    .on('dragstart', function() {
        isClicked = true;
    })
    .on('drag', function() {
        isClicked = false;

        var curr = d3.select(this)
            .attr({
                cx: d3.mouse(this)[0],
                cy: d3.mouse(this)[1]
            })
    })
    .on('dragend', function() {
        var curr = d3.select(this);
        if (!isClicked) {
            d3.select('#playground')
                .append('circle')
                .attr({
                    cx: curr.attr('cx'),
                    cy: curr.attr('cy'),
                    r: curr.attr('r')
                })
                .style({
                    fill: 'white',
                    stroke: 'red',
                    'stroke-width': '2px'
                });
        }

        curr.attr({
            cx: curr.attr('init-cx'),
            cy: curr.attr('init-cx')
        });
    });


d3.select('#drag').call(move);
d3.select('#drag').on('click', click);
function click(d) {
    isClicked = true;
}

结帐Fiddle:

More Info

答案 3 :(得分:0)

使用布尔值监视拖动是否已启动。这样,您可以停止Dragend功能。

$(document).ready(function () {

    var isDragged = false;
    var move = d3.behavior.drag()
        .on('drag', function () {

            console.log('dragging');
            isDragged = true;
            var curr = d3.select(this)
                .attr({
                    cx: d3.mouse(this)[0],
                    cy: d3.mouse(this)[1]
                })


        })
        .on('dragend', function () {
            if (!isDragged) return;
            isDragged = false;
            var curr = d3.select(this);
            d3.select('#playground')
                .append('circle')
                .attr({
                    cx : curr.attr('cx'),
                    cy : curr.attr('cy'),
                    r : curr.attr('r')
                })
                .style({
                    fill : 'white',
                    stroke : 'red',
                    'stroke-width' : '2px'
                })
            ;

            curr.attr({
                cx : curr.attr('init-cx'),
                cy : curr.attr('init-cx')
            });
        })
        ;


    d3.select('#drag').call(move);


});

答案 4 :(得分:0)

对于 D3 v4(可能适用于 v5 和 v6),您可以在 dragged 事件期间确定节点的位置,并查看是否与其原始位置不同。假设它没有,alphaTarget 永远不会被调用。

例如:

function dragstarted(d) {
    // if (!d3.event.active) simulation.alphaTarget(0.2).restart();
    d.fx = d.x;
    d.fy = d.y;
}

function dragged(d) {
    if (d3.event.active && (d.fy != d3.event.y || d.fx != d3.event.x)) {
        simulation.alphaTarget(0.5).restart();
    }

    d.fx = d3.event.x;
    d.fy = d3.event.y;
}


function dragended(d) {
    if (!d3.event.active) simulation.alphaTarget(0);
    d.fx = null;
    d.fy = null;
}