2015-07-13 77 views
1

我在左側有幾圈,右側有一個svg組。我想通過拖放將圓圈拖入svg組中。一旦我將元素放入svg組中,它應該被添加到組中。如何將拖放元素拖入svg組

到目前爲止,我創建了一個可拖動的元素和可拖動組,但無法找到任何相同的文章。

我在左邊有幾圈,右邊是一個svg組。我想通過拖放將圓圈拖入svg組中。一旦我將元素放入svg組中,它應該被添加到組中。

到目前爲止,我創建了一個可拖動的元素和可拖動組,但無法找到任何相同的文章。

演示:http://jsbin.com/wowunoluza/1/edit?html,js,output

<!doctype html> 
<html> 
    <head> 
     <title>Editor</title> 
     <meta http-equiv="x-ua-compatible" content="ie=9"/> 
     <meta http-equiv="content-type" content="text/html; charset=UTF-8"/> 
     <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.js"></script> 
     <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script> 
     <link rel="stylesheet" href="<%=request.getContextPath()%>/style.css" /> 
     <script type="text/javascript"> 
      window.onload = function() 
      { 
       var svgContainer = d3.select("body").append("svg") 
         .attr("width", 800) 
         .attr("height", 803); 

       var sidebar = svgContainer.append("rect") 
         .attr("x", 0) 
         .attr("y", 43.5) 
         .attr("width", 69) 
         .attr("height", 620) 
         .attr("stroke-width", 2) 
         .attr("stroke", "#7E7E7E") 
         .style("fill", "none"); 

       var rect = svgContainer.append("rect") 
         .attr("x", 10) 
         .attr("y", 50) 
         .attr("width", 51) 
         .attr("height", 41) 
         .attr("rx", 10) 
         .attr("stroke-width", 2) 
         .attr("stroke", "#7E7E7E") 
         .style('cursor', 'move') 
         .style("fill", "none"); 

       //Draw the Circle 
       var circle = svgContainer.append("circle") 
         .attr("cx", 35) 
         .attr("cy", 145) 
         .attr("r", 25) 
         .style("stroke-opacity", .9) 
         .style("stroke", "green") 
         .style("stroke-width", 2) 
         .style('cursor', 'move') 
         .style("fill", "white"); 

       var circle2 = svgContainer.append("circle") 
         .attr("cx", 35) 
         .attr("cy", 225) 
         .style("stroke-opacity", .9) 
         .style("stroke-width", 2) 
         .style("stroke", "red") 
         .style("fill", "white") 
         .style('cursor', 'move') 
         .attr("r", 25); 

       var circle3 = svgContainer.append("circle") 
         .attr("id", "circleToClone") 
         .attr("cx", 35) 
         .attr("cy", 310) 
         .attr("r", 25) 
         .style("fill", "white") 
         .style("stroke-width", 2) 
         .style('cursor', 'move') 
         .style("stroke", "#CDB483"); 

       var dragGroup = d3.behavior.drag() 
         .origin(function() { 
          var g = this; 
          return {x: d3.transform(g.getAttribute("transform")).translate[0], 
           y: d3.transform(g.getAttribute("transform")).translate[1]}; 
         }) 
         .on("drag", function (d, i) { 

          g = this; 
          console.log(g); 
          translate = d3.transform(g.getAttribute("transform")).translate; 
          x = d3.event.dx + translate[0], 
            y = d3.event.dy + translate[1]; 
          d3.select(g).attr("transform", "translate(" + x + "," + y + ")"); 
          d3.event.sourceEvent.stopPropagation(); 
         }); 

       var group = svgContainer.append("g") 
         .attr("id", "mygroup") 
         .call(dragGroup) 
         .style('cursor', 'move') 
         .attr("transform", "translate(20, 20)"); 

       group.append("rect") 
         .attr("x", 250) 
         .attr("y", 250) 
         .attr("width", 151) 
         .attr("height", 141) 
         .attr("rx", 10) 
         .attr("stroke-width", 2) 
         .attr("stroke", "#7E7E7E") 
         .style("fill", "white"); 

       group.append("circle") 
         .attr("cx", 330) 
         .attr("cy", 330) 
         .attr("r", 25) 
         .style("fill", "white") 
         .style("stroke-width", 1) 
         .style("stroke", "red"); 


       var drag = d3.behavior.drag() 
         .origin(function() 
         { 
          var t = d3.select(this); 
          return {x: t.attr("cx"), y: t.attr("cy")}; 
         }) 

         .on('dragend', function (d) { 
          var mouseCoordinates = d3.mouse(this); 
          if (mouseCoordinates[0] > 170) { 
           //Append new element 
           var circle2 = d3.select("svg").append("circle") 
             .classed("drg", true) 
             .attr("cx", 100) 
             .attr("cy", 100) 
             .attr("r", 20) 
             .attr("cx", mouseCoordinates[0]) 
             .attr("cy", mouseCoordinates[1]) 
             .style("fill", "white") 
             .style("stroke-width", 2) 
             .style("stroke", "#CDB483"); 
          } 
         }); 
       circle.call(drag); 
       circle2.call(drag); 
       circle3.call(drag); 
      }; 
     </script> 
    </head> 
    <body> 
     <div id="container"> 
      <div id="header" style="margin-bottom: 0;"> 
       <h1 id="title">Editor</h1> 
       <div id="footer"></div> 
      </div> 
     </div> 
    </body> 
</html> 
+0

有可能是一個更有效的方法來做到這一點(也許是一個內置的d3命令/有關碰撞的東西?),但首先想到的是要遍歷頁面上的所有組元素,並且使用'r'作爲圓形,矩形使用'width,height',確定鼠標是否在該組內(設計一個簡短的算法來確定min x,y和max x,y)。它會有點複雜,因爲'cx,cy'定義了一個圓的中間,'x,y'定義了'rect'的角,但這是一般的想法。 – JSBob

+0

函數'getBBox()'看起來很有用。它給出了相對於該形狀所屬的'g'元素的座標,因此您必須使用'g.attr(「transform」)'和'translate(x,y)'偏移座標。 [Here](http://jsfiddle.net/reblace/3rDPC/3/)是一個演示'getBBox()'的小提琴。 – JSBob

+0

@JSBob這是使用碰撞檢測實現這個更好嗎?我沒有找到有關碰撞檢測的任何教程。其唯一的代碼示例在每個地方 – kittu

回答

1

當「刪除」了一圈,你可以使用d3.transform得到g元件的電流轉換,然後檢查是否鼠標的座標位於該組中的矩形內。

然後,您可以在group附加一個新的圓圈,其座標由鼠標的座標和組的翻譯確定,它的筆劃由拖動到該組的圓的筆劃確定。

所以你.on("dragend"函數現在看起來應該是這樣:

var mouseCoordinates = d3.mouse(this); 
var groupTransform = d3.transform(group.attr("transform")); 
var groupX = groupTransform.translate[0]; 
var groupY = groupTransform.translate[1]; 
var rect = group.select("rect"); 
var rectX = +rect.attr("x"); 
var rectY = +rect.attr("y"); 
var rectWidth = +rect.attr("width"); 
var rectHeight = +rect.attr("height"); 

if (mouseCoordinates[0] > groupX + rectX 
    && mouseCoordinates[0] < groupX + rectX + rectWidth 
    && mouseCoordinates[1] > groupY + rectY 
    && mouseCoordinates[1] < groupY + rectY + rectHeight) { 
    //Append new element 
    var newCircle = group.append("circle") 
     .classed("drg", true) 
     .attr("cx", mouseCoordinates[0] - groupX) 
     .attr("cy", mouseCoordinates[1] - groupY) 
     .attr("r", 20) 
     .style("fill", "white") 
     .style("stroke-width", 2) 
     .style("stroke", d3.select(this).style("stroke")); 
} 

還有你可以改變,並添加到您的代碼,使之更好的很多東西,但這應該讓你開始。

+0

我不瞭解mousecoordinates部分。爲什麼我們在那裏使用靜態值?是否有可能像上面提到的JSBob一樣使用'getBBox()'函數? – kittu

+0

我猜碰撞檢測是這樣的嗎? – kittu

+0

我使用了靜態值,因爲我認爲'rect'的座標和大小不會改變。我已經更新了我的答案,以便動態獲取'rect'的座標和大小。 –