2014-12-03 75 views
-2

我已經設法設置了一個FIDDLE,在這裏我舉了一個例子來說明如何在svg邊界內綁定一個元素。拖動普通元素時(無旋轉),它工作正常。但在我申請這一個旋轉的物體時,問題出現了:使用快照限制邊界內的旋轉對象SVG

var s = Snap("#svgout"); 
var ROOM_WIDTH = 400; 
var ROOM_HEIGHT = 200; 
var SVG_BOUNDARY = s.rect(0, 0, ROOM_WIDTH, ROOM_HEIGHT); 
SVG_BOUNDARY.attr({ 
    "stroke": "#FF0000", 
    "fill": "#FFFFFF", 
    id: "room-svg-boundary" 
}); 
var BEFORE_ROTATION_GETBBOX = []; 

s.attr({ 
    viewBox: "0 0 " + ROOM_WIDTH + " " + ROOM_HEIGHT 
}); 
(function() { 

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

    Element.prototype.limitDragging = function(params) { 
     this.data('minx', params.minx); 
     this.data('miny', params.miny); 
     this.data('maxx', params.maxx); 
     this.data('maxy', params.maxy); 
     this.data('x', params.x); 
     this.data('y', params.y); 
     this.data('ibb', this.getBBox()); 
     this.data('ot', this.transform().local); 
     this.drag(limitMoveDrag, limitStartDrag); 
     return this; 
    }; 

    function limitMoveDrag(dx, dy, posx, posy, ev) { 
     var tdx, tdy; 
     var sInvMatrix = this.transform().globalMatrix.invert(); 
     sInvMatrix.e = sInvMatrix.f = 0; 
     tdx = sInvMatrix.x(dx, dy); 
     tdy = sInvMatrix.y(dx, dy); 

     this.data('x', +this.data('ox') + tdx); 
     this.data('y', +this.data('oy') + tdy); 
     if (this.data('x') > this.data('maxx') - this.data('ibb').width) { 
     this.data('x', this.data('maxx') - this.data('ibb').width) 
     }; 
     if (this.data('y') > this.data('maxy') - this.data('ibb').height) { 
     this.data('y', this.data('maxy') - this.data('ibb').height) 
     }; 
     if (this.data('x') < this.data('minx')) { 
     this.data('x', this.data('minx')) 
     }; 
     if (this.data('y') < this.data('miny')) { 
     this.data('y', this.data('miny')) 
     }; 

     this.transform(this.data('ot') + "t" + [this.data('x'), this.data('y')]); 
    }; 

    function limitStartDrag(x, y, ev) { 
     this.data('ox', this.data('x')); 
     this.data('oy', this.data('y')); 
    }; 
    }); 

})(); 

var SETUP_DRAG_MOVEMENT = function(ELEM, disable) { 
    if (disable != undefined && disable == true) { 
    ELEM.undrag(); 
    } else { 
    var RECT_BOUNDARY = s.getBBox(); 
    var ELEM_BOX = ELEM.getBBox(); 
    var min_x = -ELEM_BOX.cx + ELEM_BOX.width/2; 
    var max_x = RECT_BOUNDARY.x2 - ELEM_BOX.x2 + ELEM_BOX.width; 
    var min_y = -ELEM_BOX.cy + ELEM_BOX.height/2; 
    var max_y = RECT_BOUNDARY.y2 - ELEM_BOX.y2 + ELEM_BOX.height; 

    ELEM.limitDragging({ 
     x: 0, 
     y: 0, 
     minx: min_x, 
     miny: min_y, 
     maxx: max_x, 
     maxy: max_y 
    }); 
    } 
} 

var SETUP_DRAG_MOVEMENT_ROTATED = function(ELEM, disable) { 
    if (disable != undefined && disable == true) { 
    BEFORE_ROTATION_GETBBOX[ELEM.node.id] = ELEM.getBBox(); 
    ELEM.undrag(); 
    } else { 
    var RECT_BOUNDARY = s.getBBox(); 
    console.log(RECT_BOUNDARY); 
    var ELEM_BOX = (BEFORE_ROTATION_GETBBOX[ELEM.node.id] != undefined && typeof BEFORE_ROTATION_GETBBOX[ELEM.node.id] == "object") ? BEFORE_ROTATION_GETBBOX[ELEM.node.id] : ELEM.getBBox(); 

    var min_x = -ELEM_BOX.x; 
    var max_x = RECT_BOUNDARY.x2 - ELEM_BOX.x2 + ELEM_BOX.width; 
    var min_y = -ELEM_BOX.y; 
    var max_y = RECT_BOUNDARY.y2 - ELEM_BOX.y2 + ELEM_BOX.height; 

    ELEM.limitDragging({ 
     x: 0, 
     y: 0, 
     minx: min_x, 
     miny: min_y, 
     maxx: max_x, 
     maxy: max_y 
    }); 
    } 
} 

var DBLCLICK_HANDLER = function(ELEM) { 
    SETUP_DRAG_MOVEMENT(THIS_RECT, true); 
    var THIS_ELEM_BB = ELEM.getBBox(); 
    var transformProp = new Snap.Matrix(); 
    transformProp.rotate(45, THIS_ELEM_BB.cx, THIS_ELEM_BB.cy); 
    transformProp.add(ELEM.matrix); 
    ELEM.transform(transformProp); 
    SETUP_DRAG_MOVEMENT_ROTATED(THIS_RECT, false); 
} 

var myCircle = s.circle(380, 20, 20).attr({ 
    fill: 'blue' 
}); 
var THIS_CIRCLE_LABEL = s.paper.text(376, 25, "1").attr({ 
    fill: "#FFFFFF" 
}); 
var THIS_CIRCLE = s.group(myCircle, THIS_CIRCLE_LABEL); 
THIS_CIRCLE.attr({ 
    id: "THIS_CIRCLE" 
}); 
SETUP_DRAG_MOVEMENT_ROTATED(THIS_CIRCLE, false); 

var myRect = s.rect(0, 0, 30, 30).attr({ 
    fill: 'green' 
}); 
var THIS_RECT_LABEL = s.paper.text(11, 19, "2").attr({ 
    fill: "#FFFFFF" 
}); 
var THIS_RECT = s.group(myRect, THIS_RECT_LABEL); 
THIS_RECT.attr({ 
    id: "THIS_RECT" 
}); 
SETUP_DRAG_MOVEMENT_ROTATED(THIS_RECT, false); 

THIS_RECT.node.addEventListener("dblclick", function() { 
    DBLCLICK_HANDLER(THIS_RECT); 
}, false); 
<script src="http://snapsvg.io/assets/js/snap.svg-min.js"></script> 
<p>Double click on the rectangle to rotate it and then try to drag. When you drag without rotating, it's perfect (The drag boundary). But while dragging a rotated object, then the problem arises..</p> 
<svg id="svgout" height="400" width="600"></svg> 

如何解決這個問題呢?

+0

Desribe您的問題更多。 – Refilon 2014-12-03 08:24:11

+0

去那個小提琴,只需雙擊矩形旋轉它,然後嘗試拖動它。我想要這個旋轉的對象被綁定在svg邊界內,這不是偶然發生的。 – Pritam 2014-12-03 10:30:25

回答

0

爲包括我的一些舊代碼,以爲我會做一個答案....

本來不考慮現有的轉換更容易。我寫了一些更新的代碼,可以做到這一點......

不同的主要位是getInversePoint()函數,該函數獲取屏幕的逆向變換。我也改變了轉換的順序,所以元素總是首先被平移。

Example

Element.prototype.getInversePoint = function(x, y) { 
     var pt = this.paper.node.createSVGPoint(); 
     pt.x = x; pt.y = y; 
     return pt.matrixTransform(this.paper.node.getScreenCTM().inverse()); 
} 

Element.prototype.limitDrag = function(params) { 
    this.data('dragParams', params); 
    this.data('x', params.x); this.data('y', params.y); 
    this.drag(limitMoveDrag, limitStartDrag); 
    return this;  
}; 

function limitMoveDrag(xxdx, xxdy, ax, ay) { 
    var tdx, tdy; 
    var params = this.data('dragParams'); 
    var pt = this.getInversePoint(ax, ay); 
    var dx = pt.x - this.data('op').x; 
    var dy = pt.y - this.data('op').y; 

    var ibb = this.data('ibb'); 
    if(ibb.x + ibb.width + +dx > params.maxx) 
     { dx = params.maxx - (ibb.x + ibb.width) }; 

    if(ibb.y + ibb.height + +dy > params.maxy) 
     { dy = params.maxy - (ibb.y + ibb.height) }; 
    if(ibb.x + +dx < params.minx) { dx = params.minx - ibb.x; }; 
     if(ibb.y + +dy < params.miny) { dy = params.miny - ibb.y; }; 

    this.transform( "t" + [ dx, dy ] + this.data('ot').toTransformString()); 
}; 

function limitStartDrag(x, y, ev) { 
    this.data('ibb', this.getBBox()); 
    this.data('op', this.getInversePoint(x, y)); 
    this.data('ot', this.transform().localMatrix); 
};