d3js предотвращает перетаскивание на событие click

Я пытаюсь нарисовать пользовательский интерфейс в d3js, где у меня есть верхняя панель, и я должен иметь возможность dragи dropэлементы группы и скопировать их. Я достиг этой цели, но в моем коде есть ошибка. То, что я действительно хочу сделать, это перетащить 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/

javascript,d3.js,svg,

1

Ответов: 4


1 принят

Надеюсь, это будет полезно для вас, посмотрите. Я добавил немного кода в «dragend», то есть здесь я решаю, создавать ли / добавлять круг на площадку или нет, используя атрибуты окружности, такие как init-cx и init-cy. Код, который я добавил,

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
}

скрипка

: D


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')
      });
    }
});

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


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:

Больше информации


0

Используйте boolean для проверки того, инициировано ли перетаскивание или нет. Таким образом, вы можете остановить функцию 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);


});
JavaScript, d3.js, SVG,
Похожие вопросы