javascript - 如何用JS拖动多个圆圈?

标签 javascript d3.js

我使用 d3 画了一堆圆圈。我可以轻松地拖动其中一个圆圈并跟踪其 cx 和 cy 位置。

 var width= 800;
 var height=600;
 svg= d3.select("body").select(".div1").append("svg")
                            .attr("width", width)
                            .attr("height",height);
 transformed_data =  [
                  [5, 20], [480, 90], [250, 50], [100, 33], [330, 95],
                  [410, 12], [475, 44], [25, 67], [85, 21], [220, 88] 
                ];

 X = [0,800];
 Y = [0,600];

 xScale =d3.scale.linear().domain(X).range([70, width-70]);
 yScale =d3.scale.linear().domain(Y).range([70, height-70]);

 drag = d3.behavior.drag()
          .on("drag", function(d,i) {
                d3.select(this).attr("cx", d3.event.x);
                d3.select(this).attr("cy", d3.event.y);
          })
         .on("dragend",function(d,i){

         });

svg.selectAll('circle')
        .data(transformed_data)
        .enter()
        .append("circle")
        .attr("id", function(d,i){return "id_" + i.toString();})
        .attr("cx", function(d,i){return xScale(transformed_data[i][0]);})
        .attr("cy", function(d,i){return yScale(transformed_data[i][1]);}) 
        .attr("r",10)
        .call(drag);

但是,我不知道如何使用鼠标选择多个圆圈并将它们拖动在一起。有什么想法,例子吗?

最佳答案

有一个实现允许您拖动多个元素,该链接由@Lars 提供,效果很好,但交互不自然,我个人不喜欢它。这是代码:Drag multiple elements that aren't grouped in a `g` tag?

经过一段时间的寻找。我最终得到了以下代码,它运行完美,我相信交互非常自然。

<html>
 <head>
   <title>jQuery UI Selectable - Serialize</title>
   <link rel="stylesheet" href="//code.jquery.com/ui/1.11.4/theme/smoothness/jquery-ui.css">
   <script src="http://code.jquery.com/jquery-1.11.0.min.js"></script>
   <script src="http://code.jquery.com/ui/1.11.4/jquery-ui.js"></script>
   <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js"></script>
   <link rel="stylesheet" href="/resources/demos/style.css">  

  <style>
      rect.selection {
          stroke: black;
          stroke-dasharray: 4px;
          stroke-opacity  : 0.9;
          fill: transparent;
       }
      .state circle {
          stroke  : gray;
          cursor  : pointer;
       }
      .state {
          fill    : black;
      }
      .selected{
          fill    : red;
      }

   </style>

   <body> 
      <div class="div1"></div>  
   </body>


<script type="text/javascript">

var width = 800,
    radius=10,
    height = 600;

   svg= d3.select("body").select(".div1").append("svg")
                            .attr("width", width)
                            .attr("height",height);
   var transformed_data= d3.range(10).map(function(d) {
       return {
         x: parseInt(Math.random() * width),
         y: parseInt(Math.random() * height),
       }
     });

    // Drag Evenet 
    drag = d3.behavior.drag()
            .on("drag", function( d, i) {
                    var selection = d3.selectAll('.selected');
                    console.log(selection[0] + "---"+selection[1]);
                    svg.selectAll( "rect.selection").remove();
                    if(selection[0].indexOf(this)==-1) {
                        selection = d3.select(this);
                        selection.classed("selected", true);
                    } 
                    selection.attr("cx", function(d){ d.x += d3.event.dx; return d.x;})
                    selection.attr("cy", function(d,i){d.y += d3.event.dy; return d.y;})    
            });

    gStates = svg.selectAll('circle')
                 .data(transformed_data)
                 .enter()
                 .append("circle")
                 .attr("class","state")
                 .attr("id", function(d,i){return "id_" + i.toString();})
                 .attr("cx", function(d,i){return d.x;})
                 .attr("cy", function(d,i){return d.y;}) 
                 .attr("r",10)
                 .call(drag);

    svg.on( "mousedown", function() {
            if(!d3.event.ctrlKey) {
                    d3.selectAll(".selected").classed( "selected", false);
            }
            var p = d3.mouse(this);
            svg.append( "rect")
               .attr({
                    class   : "selection",
                    x       : p[0],
                    y       : p[1],
                    width   : 0,
                    height  : 0
                })
        })
       .on( "mousemove", function() {
            var s = svg.select( "rect.selection");
            if( !s.empty()) {
                var p = d3.mouse( this),
                    d = {
                        x       : parseInt( s.attr( "x"), 10),
                        y       : parseInt( s.attr( "y"), 10),
                        width   : parseInt( s.attr( "width"), 10),
                        height  : parseInt( s.attr( "height"), 10)
                    },
                    move = {
                        x : p[0] - d.x,
                        y : p[1] - d.y
                    };

                if( move.x < 1 || (move.x*2<d.width)) {
                    d.x = p[0];
                    d.width -= move.x;
                } else {
                    d.width = move.x;       
                }

                if( move.y < 1 || (move.y*2<d.height)) {
                    d.y = p[1];
                    d.height -= move.y;
                } else {
                    d.height = move.y;       
                }

                s.attr( d);
                d3.selectAll( ".state").each( function( state_data, i) {
                    if( 
                        !d3.select(this).classed("selected") && 
                            // inner circle inside selection frame
                        state_data.x-radius>=d.x && state_data.x+radius<=d.x+d.width && 
                        state_data.y-radius>=d.y && state_data.y+radius<=d.y+d.height
                    ) {
                        d3.select(this)
                        .classed( "selection", true)
                        .classed( "selected", true);
                    }
                });
            }
        })

        .on( "mouseup", function() {
              // remove selection frame
            svg.selectAll( "rect.selection").remove();

              // remove temporary selection marker class
            d3.selectAll( '.state.selection').classed( "selection", false);
        })
        .on( "mouseout", function() {
            if( d3.event.relatedTarget.tagName=='HTML') {
                    // remove selection frame
                svg.selectAll( "rect.selection").remove();

                    // remove temporary selection marker class
                d3.selectAll( '.state.selection').classed( "selection", false);
            }
        });
</script>
  </head>

关于javascript - 如何用JS拖动多个圆圈?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32541282/

相关文章:

html - 页面刷新时过渡持续时间不起作用

javascript - d3.js 轴中的科学记数法

javascript - d3.js 动态附加具有可变力边界的群

javascript - 无法使用 d3.js 显示 JSON 映射

javascript - d3 x 轴有一个不正确的值

javascript - 模态打开时向正文添加类

javascript - 如何在非 Promise 函数中测试 Promise 回调?

javascript - 有没有更好的方法来获取 outerHtml?

javascript - 根据字符串对 float 进行排序?

javascript - 将输入限制为 5 个字符(如果是整数)或 8 个字符(带分数)