2015-12-15 31 views
0

我希望能夠使用Snap SVG將一組套件作爲一組拖動。到目前爲止,我只能將子集(矩形和文本框)拖放爲一個項目,但我試圖實現的是集體「表格」是可拖動的,而內部的字段保持爲獨立形狀我可以保持它們之間的聯繫。這可能嗎? (編輯 - 我是從拉斐爾重構捕捉並試圖把一套成組拖動)Snap svg拖動一組套件

這裏是對plunker鏈接:http://plnkr.co/edit/9ewo0OcgThwB4KyMTxIL?p=preview

而且也低於代碼:

// Code goes here 

Snap.plugin( function(Snap, Element, Paper, global) { 

Paper.prototype.connection = function (obj1, obj2, line, bg) { 
    if (obj1.line && obj1.from && obj1.to) { 
     line = obj1; 
     obj1 = line.from; 
     obj2 = line.to; 
    } 
    var bb1 = obj1.getBBox(), 
     bb2 = obj2.getBBox(), 
     p = [{x: bb1.x + bb1.width/2, y: bb1.y - 1}, 
     {x: bb1.x + bb1.width/2, y: bb1.y + bb1.height + 1}, 
     {x: bb1.x - 1, y: bb1.y + bb1.height/2}, 
     {x: bb1.x + bb1.width + 1, y: bb1.y + bb1.height/2}, 
     {x: bb2.x + bb2.width/2, y: bb2.y - 1}, 
     {x: bb2.x + bb2.width/2, y: bb2.y + bb2.height + 1}, 
     {x: bb2.x - 1, y: bb2.y + bb2.height/2}, 
     {x: bb2.x + bb2.width + 1, y: bb2.y + bb2.height/2}], 
     d = {}, dis = []; 
    for (var i = 0; i < 4; i++) { 
     for (var j = 4; j < 8; j++) { 
      var dx = Math.abs(p[i].x - p[j].x), 
       dy = Math.abs(p[i].y - p[j].y); 
      if ((i == j - 4) || (((i != 3 && j != 6) || p[i].x < p[j].x) && ((i != 2 && j != 7) || p[i].x > p[j].x) && ((i != 0 && j != 5) || p[i].y > p[j].y) && ((i != 1 && j != 4) || p[i].y < p[j].y))) { 
       dis.push(dx + dy); 
       d[dis[dis.length - 1]] = [i, j]; 
      } 
     } 
    } 
    if (dis.length == 0) { 
     var res = [0, 4]; 
    } else { 
     res = d[Math.min.apply(Math, dis)]; 
    } 
    var x1 = p[res[0]].x, 
     y1 = p[res[0]].y, 
     x4 = p[res[1]].x, 
     y4 = p[res[1]].y; 
    dx = Math.max(Math.abs(x1 - x4)/2, 10); 
    dy = Math.max(Math.abs(y1 - y4)/2, 10); 
    var x2 = [x1, x1, x1 - dx, x1 + dx][res[0]].toFixed(3), 
     y2 = [y1 - dy, y1 + dy, y1, y1][res[0]].toFixed(3), 
     x3 = [0, 0, 0, 0, x4, x4, x4 - dx, x4 + dx][res[1]].toFixed(3), 
     y3 = [0, 0, 0, 0, y1 + dy, y1 - dy, y4, y4][res[1]].toFixed(3); 
    var path = "M" + x1.toFixed(3) + "," + y1.toFixed(3) + "C" + [ x2, y2, x3, y3, x4.toFixed(3), y4.toFixed(3)].join(); 
    if (line && line.line) { 
     line.bg && line.bg.attr({path: path}); 
     line.line.attr({path: path}); 
    } else { 
     var color = "#000"; 
     return { 
      bg: bg && bg.split && this.path(path).attr({stroke: bg.split("|")[0], fill: "none", "stroke-width": bg.split("|")[1] || 3}), 
      line: this.path(path).attr({stroke: color, fill: "none"}), 
      from: obj1, 
      to: obj2 
     }; 
    } 
} 

}); 


var el; 
(function() { 
    var color, i, ii, tempS, tempT; 
    var dragger = function() { 
     this.data("ox", this.attr("x")); 
     this.data("oy", this.attr("y")); 
     if (this.type != "text") this.animate({"fill-opacity": .2}, 500); 

     //this.pair.ox = this.pair.attr("x"); 
     this.pair.data("ox", this.pair.attr("x")); 
     //this.pair.oy = this.pair.attr("y"); 
     this.pair.data("oy", this.pair.attr("y")); 
     if (this.pair.type != "text") this.pair.animate({"fill-opacity": .2}, 500); 
    }, 
     move = function (dx, dy) { 
      var att = {x: parseInt(this.data("ox")) + dx, y: parseInt(this.data("oy")) + dy}; 
      this.attr(att); 
      //att = {x: this.pair.ox + dx, y: this.pair.oy + dy}; 
      att = {x: this.pair.data("oy") + dx, y: this.pair.data("oy") + dy}; 
      this.pair.attr(att); 
      for (var i = connections.length; i--;) { 
       s.connection(connections[i]); 
      } 
     }, 
     up = function() { 
      if (this.type != "text") this.animate({"fill-opacity": 0}, 500); 

      // Fade paired element on mouse up 
      if (this.pair.type != "text") this.pair.animate({"fill-opacity": 0}, 500); 
     }, 
     s = Snap("#svgout"), 
     connections = [], 
     shapes = [ // Users 
        s.rect(250, 80, 80, 20), 
        s.rect(250, 100, 80, 20), 
        s.rect(250, 120, 80, 20), 
        // Groups 
        s.rect(380, 80, 80, 20), 
        s.rect(380, 100, 80, 20), 
        s.rect(380, 120, 80, 20) 
       ], 
     texts = [ 
        s.text(290, 90, "Users"), //0 
        s.text(290, 110, "id"), //1 
        s.text(290, 130, "name"), //2 
        s.text(420, 90, "Groups"), //3 
        s.text(420, 110, "id"), //4 
        s.text(420, 130, "owner") //5 
       ]; 
    for (var i = 0, ii = shapes.length; i < ii; i++) { 
     color = "grey"; 
     tempS = shapes[i].attr({fill: color, stroke: color, "fill-opacity": 0, "stroke-width": 2, cursor: "move"}); 
     tempT = texts[i].attr({fill: color, stroke: "none", "font-size": 15, cursor: "move"}); 


     //shapes[i].drag(move, dragger, up); 
     //texts[i].drag(move, dragger, up); 

     // Associate the elements 
     //tempS.pair = tempT; 
     //tempT.pair = tempS; 
    } 
    connections.push(s.connection(shapes[1], shapes[5])); 
    var group1 = s.g(shapes[0], shapes[1], shapes[2], texts[0], texts[1], texts[2]); 
    group1.drag(move, dragger, up); 

})(); 
+0

如果您不需要較早的瀏覽器支持,然後只需拖動組,可能會更簡單地使用Snap。否則,我會爲每個「組」的元素設置一個集合,而不是一個數組,然後對該組應用一個變換來存儲拖動處理程序的原始位置,類似於您所做的操作。對於我想的答案來說,重做所有工作都有點過分,但如果你陷入困境,我肯定會有人會提供幫助。 – Ian

+0

@Ian謝謝我將嘗試重構使用Snap並從那裏出發,感謝它! –

+0

@Ian在這裏更新了plunker:http://plnkr.co/edit/9ewo0OcgThwB4KyMTxIL?p=preview with refactored to use Snap .... have only managed to get the faading out as a group but not dragging as a group。有什麼建議麼? –

回答

1

由於您不需要擔心套件,因此可以更輕鬆一點。 Graffle /轉換代碼工作正常,但它只適用於rects和圓圈,所以它實際上可能看起來更復雜一些,但我們可以讓它在任何通過變換拖動的形狀上工作。我不認爲Snap現在做這個(雖然有getBBox(1)方法我不認爲這樣做,但我們需要創建一個插件來獲得一個邊界框來說明它的轉換,我不認爲Snap現在做這個(雖然有getBBox方法(1)我不認爲這個工程相當,因爲我以爲)

所以一個插件來獲得轉化BBOX開始(也有可能是一種更有效的方式,但只是做一個快速的解決方案)......

Element.prototype.getTransformedBB = function() { 
    var bb = this.getBBox(1); 
    var t = this.node.getTransformToElement(this.paper.node); 
    var m = Snap.matrix(t); 
    var obj = { x: m.x(bb.x, bb.y), y: m.y(bb.x, bb.y), x2: m.x(bb.x2, bb.y2), y2: m.y(bb.x2, bb.y2), 
      cx: m.x(bb.cx, bb.cy), cy: m.y(bb.cy, bb.cy) } 
    obj['width'] = obj.x2 - obj.x 
    obj['height'] = obj.y2 - obj.y 
    return obj; 
}; 

然後代替getBBox的()在連接代碼中,使用getTransformedBB ...

var bb1 = obj1.getTransformedBB(), 
    bb2 = obj2.getTransformedBB(), 

現在使用的是快,你可以使用一個簡單的拖動處理程序,將所有形狀工作...

var dragger = function() { 

    this.data('origTransform', this.transform().local) 
    this.animate({"fill-opacity": .5}, 500); 
}, 
move = function (dx, dy) { 
     this.attr({ transform: this.data('origTransform') + (this.data('origTransform') ? "T" : "t") + [dx, dy]}) 
     for (var i = connections.length; i--;) { 
      s.connection(connections[i]); 
     } 
}, 
up = function() { 
     this.animate({"fill-opacity": 1}, 500); 
}, 

如果你只使用rects,你可能並不需要的東西transformedBB,但我認爲這個解決方案可能適用於更多奇怪的團體。

plunker

有與來自組的頂部連接的輕微奇怪,不知道這是與原始代碼或什麼錯誤,但如果需要,通過把一個白色的你可能圍繞它得到填寫矩形並確保連接後添加。

+0

非常感謝你!你一直非常有幫助......並且看起來很容易。不夠感謝你。 –