首页 > 解决方案 > 如果用户单击 d3.js 中的圆形,如何防止拖动?

问题描述

我有 group 元素,它有 circle 和 rect 元素。用户可以拖动 group 元素,因此 rect 和 circle 元素都会移动。它工作正常。但是如果用户单击圆形元素,我需要防止拖动。JS小提琴

const x = 100;
var y = 100;

var grid = d3.select("#svg-area");

var g = grid.append("g")
  .attr("transform", `translate(${x},${y})`)
  .call(d3.drag()
    .on("drag", function() {
      var x1 = d3.event.x - 30;
      var y1 = d3.event.y - 10;
      d3.select(this).attr("transform", "translate(" +
        (x1) + "," + (y1) + ")")
    }));
newNode(g);

function newNode(g, text) {

  var textWid = 100;
  console.log('wid ', textWid);
  g.append("rect")
    .attr("class", "new-nodes")
    .attr("x", '10')
    .attr("y", '0')
    .attr("rx", '6')
    .attr("ry", '6')
    .attr("width", textWid)
    .attr("height", '35')
    .style("fill", "#8c259f")
    .style("stroke", "#222")
    .style("cursor", "move");

  g.append("circle")
    .attr("class", "new-nodes")
    .attr("cx", '10')
    .attr("cy", '17')
    .attr("r", '6')
    .style("fill", "#dedede")
    .style("stroke", "#b2b0b0")
    .style("cursor", "pointer")
    .on("click", function(d) {
      /*             d3.event.preventDefault();
                  d3.event.stopPropagation();
                   */
    });
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.13.0/d3.min.js"></script>
<svg id="svg-area" class="chart-area" width="500" height="500" pointer-events="all" style="cursor: crosshair; touch-action: none;">
</svg>

标签: javascriptsvgd3.js

解决方案


最简单的方法(最接近您的代码的方法)是更改on("click"on("mousedown". 再次释放鼠标按钮时会注册“click”事件。在此之前清楚地注册了“mousedown”事件。而mousedown事件是触发“dragstart”的事件。

const x = 100;
var y = 100;

var grid = d3.select("#svg-area");

var g = grid.append("g")
  .attr("transform", `translate(${x},${y})`)
  .call(d3.drag()
    .on("drag", function() {
      var x1 = d3.event.x - 30;
      var y1 = d3.event.y - 10;
      d3.select(this).attr("transform", "translate(" +
        (x1) + "," + (y1) + ")")
    }));
newNode(g);

function newNode(g, text) {

  var textWid = 100;
  console.log('wid ', textWid);
  g.append("rect")
    .attr("class", "new-nodes")
    .attr("x", '10')
    .attr("y", '0')
    .attr("rx", '6')
    .attr("ry", '6')
    .attr("width", textWid)
    .attr("height", '35')
    .style("fill", "#8c259f")
    .style("stroke", "#222")
    .style("cursor", "move");

  g.append("circle")
    .attr("class", "new-nodes")
    .attr("cx", '10')
    .attr("cy", '17')
    .attr("r", '6')
    .style("fill", "#dedede")
    .style("stroke", "#b2b0b0")
    .style("cursor", "pointer")
    .on("mousedown", function(d) {
      d3.event.preventDefault();
      d3.event.stopPropagation();
    });
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.13.0/d3.min.js"></script>
<svg id="svg-area" class="chart-area" width="500" height="500" pointer-events="all" style="cursor: crosshair; touch-action: none;">
</svg>


或者,您可以将事件移动到矩形并使用d3.drag().container. 通常,d3.drag计算事件与父元素之间的距离。现在,我们需要祖父母,因为父母(g元素)是我们想要拖动的东西。

我还更改了g元素以使用基准对象,因此您可以更轻松地移动它。

var grid = d3.select("#svg-area");

var g = grid.append("g")
  .datum({
    x: 100,
    y: 100
  })
  .attr("transform", function(d) {
    return `translate(${d.x},${d.y})`;
  });
newNode(g);

function newNode(g, text) {

  var textWid = 100;
  console.log('wid ', textWid);
  g.append("rect")
    .attr("class", "new-nodes")
    .attr("x", '10')
    .attr("y", '0')
    .attr("rx", '6')
    .attr("ry", '6')
    .attr("width", textWid)
    .attr("height", '35')
    .style("fill", "#8c259f")
    .style("stroke", "#222")
    .style("cursor", "move")
    .call(d3.drag()
      .container(grid.node())
      .on("drag", function() {
        d3.select(this.parentNode)
          .attr("transform", function(d) {
            d.x += d3.event.dx;
            d.y += d3.event.dy;
            return `translate(${d.x},${d.y})`;
          });
      }));

  g.append("circle")
    .attr("class", "new-nodes")
    .attr("cx", '10')
    .attr("cy", '17')
    .attr("r", '6')
    .style("fill", "#dedede")
    .style("stroke", "#b2b0b0")
    .style("cursor", "pointer");
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.13.0/d3.min.js"></script>
<svg id="svg-area" class="chart-area" width="500" height="500" pointer-events="all" style="cursor: crosshair; touch-action: none;">
</svg>


推荐阅读