D3 - 跨组拖动多个元素

时间:2018-02-07 20:48:16

标签: javascript d3.js

我试图实现D3拖拽行为,我没有找到一个例子。

下面的代码创建了几行,每行都有一个矩形,圆形和椭圆形,并为圆圈启用了拖动功能。



<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Drag many</title>
    <style media="screen">
    .active {
      stroke: #000;
      stroke-width: 2px;
    }
    </style>
  </head>
  <body>
    <svg width=1000 height=500></svg>

    <script src="https://d3js.org/d3.v4.min.js" charset="utf-8"></script>
    <script type="text/javascript">
      var svg=d3.select("svg"),
        mainGroup = svg.append("g");

      var squareData = [
        {x:25, y:23, width:15, height:15},
        {x:25, y:63, width:15, height:15}
      ];

      var circleData = [
       {cx:60, cy:30, r:10},
       {cx:60, cy:70, r:10}
      ];

      var ellipseData = [
       {cx:90, cy:30, rx:10, ry:15},
       {cx:90, cy:70, rx:10, ry:15}
      ];

      var squareGroup = mainGroup.append("g");
      squareGroup.selectAll(null)
      .data(squareData)
        .enter().append("rect")
        .attr("class", (d,i)=>`rectGroup row_${i+1}`)
        .attr("x", d=>d.x)
        .attr("y", d=>d.y)
        .attr("width", d=>d.width)
        .attr("height", d=>d.height)
        .attr("fill", "blue");

      circleGroup = mainGroup.append("g");
      circleGroup.selectAll(null)
      .data(circleData)
        .enter().append("circle")
        .attr("class", (d,i)=>`circleGroup row_${i+1}`)
        .attr("cx", d=>d.cx)
        .attr("cy", d=>d.cy)
        .attr("r", d=>d.r)
        .attr("fill", "red")
        .call(d3.drag()
          .on("start", dragstarted)
          .on("drag", dragged)
          .on("end", dragended));

      ellipseGroup = mainGroup.append("g");
      ellipseGroup.selectAll(null)
      .data(ellipseData)
        .enter().append("ellipse")
        .attr("class", (d,i)=>`ellipseGroup row_${i+1}`)
        .attr("cx", d=>d.cx)
        .attr("cy", d=>d.cy)
        .attr("rx", d=>d.rx)
        .attr("ry", d=>d.ry)
        .attr("fill", "green");

      function dragstarted(d){
        d3.select(this).classed("active", true);
      }

      function dragended(d){
        d3.select(this).classed("active", false);
      }

      function dragged(d){
        //var dx = d3.event.x - d3.select(this).attr("cx")
        d3.select(this).attr("cx", d.x = d3.event.x);
        // I really need to move all the elements in this row here, 
        // with the circle being the pivot...
      }


    </script>
  </body>
</html>
&#13;
&#13;
&#13;

我想修改圆圈的拖动行为,用它拉动整行,而不是单独移动。

我怎样才能做到这一点?

2 个答案:

答案 0 :(得分:1)

看起来你给每一行一个类而不是:

function dragged(d){d3.select(this).attr("cx", d.x = d3.event.x);}

获取该行的类(来自代码的外观,它应该是第二个类):var thisRow = d3.select(this).attr("class").split()[1];

.split()将拆分空格,这就是让类列表吐出结果的方式。

让班级移动所有课程后:

d3.selectAll("." + thisRow).attr("cx", d.x = d3.event.x);

答案 1 :(得分:0)

我不确定是否有更好的方法可以找到row,但是我是如何使用@pmkroeker

中的概念解决它的方法
  function dragged(d){
    var deltaX = d3.event.x - d3.select(this).attr("cx");
    d3.select(this).attr("cx", d.x = d3.event.x); // move the circle

    // find the row
    var row = d3.select(this).attr("class").split(/\s+/).filter(s=>s.startsWith("row_"))[0];

    // grab other elements of the row and move them as well
    d3.selectAll("."+row).filter(".rectGroup").attr("x", d=>d.x = d.x+deltaX);
    d3.selectAll("."+row).filter(".ellipseGroup").attr("cx", d=>d.cx = d.cx+deltaX);
  }