我设法设置FIDDLE,我举例说明了如何绑定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 :(得分:0)
因为这包括我的一些旧代码,我想我会回答......
最初,这不会更容易考虑现有的转换。我写了一些更新的代码,可以做到这一点......
不同的主要部分是getInversePoint()函数,它获取到屏幕的逆变换。此外,我已经改变了转换的顺序,因此元素总是先被平移。
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);
};