define(function (require, exports, module) {
|
|
var Bezier = require('graphic/bezier');
|
|
var BezierPoint = require('graphic/bezierpoint');
|
|
var Vector = require('graphic/vector');
|
|
var Pen = require('graphic/pen');
|
|
function mid(a, b) {
|
|
return (a + b) / 2;
|
|
}
|
|
function getSnapPoints( snaper ) {
|
|
if(snaper.getSnapPoints) {
|
|
return snaper.getSnapPoints();
|
|
}
|
|
var box = snaper.getRenderBox();
|
|
var x1 = box.x, x2 = box.x + box.width,
|
|
y1 = box.y, y2 = box.y + box.height,
|
|
xm = mid(x1, x2), ym = mid(y1, y2);
|
|
return [
|
|
{ x: xm, y: y1, type: 'top' }, // top
|
|
{ x: x2, y: ym, type: 'right' }, // right
|
|
{ x: xm, y: y2, type: 'bottom' }, // bottom
|
|
{ x: x1, y: ym, type: 'left' } // left
|
|
];
|
|
}
|
|
var DIR_NORMALS = {
|
|
top: new Vector(0, -1),
|
|
left: new Vector(-1, 0),
|
|
bottom: new Vector(0, 1),
|
|
right: new Vector(1, 0)
|
|
};
|
|
function fillNormal( snapPoint ) {
|
|
if(snapPoint.normal) {
|
|
return;
|
|
}
|
|
snapPoint.normal = DIR_NORMALS[snapPoint.type] || DIR_NORMALS.left;
|
|
}
|
|
return require('core/class').createClass("SnapCurve", {
|
|
base: Bezier,
|
|
constructor: function( start, end ) {
|
|
this.callBase();
|
|
this.setStartSnaper( start );
|
|
this.setEndSnaper( end );
|
|
this.init();
|
|
this.updateConnection();
|
|
},
|
|
init: function() {
|
|
this.addPoint(this.startBesierPoint = new BezierPoint());
|
|
this.addPoint(this.endBesierPoint = new BezierPoint());
|
|
this.stroke(new Pen('red', 3));
|
|
},
|
|
bindSnaper: function( snaper ) {
|
|
var me = this;
|
|
snaper.on('shapeupdate', function() {
|
|
me.updateConnection();
|
|
});
|
|
},
|
|
setStartSnaper: function( snaper ) {
|
|
this.start = snaper;
|
|
this.bindSnaper(snaper);
|
|
},
|
|
setEndSnaper: function( snaper ) {
|
|
this.end = snaper;
|
|
this.bindSnaper(snaper);
|
|
},
|
|
isReady: function() {
|
|
return !!(this.start && this.end);
|
|
},
|
|
calcEndPoints: function() {
|
|
var startEnds = getSnapPoints(this.start),
|
|
endEnds = getSnapPoints(this.end);
|
|
var nearStart, nearEnd, minDistance = Number.MAX_VALUE;
|
|
var i, j, startEnd, endEnd, distance;
|
|
|
|
// 寻找最近的粘附点
|
|
// 暴力解法:可优化但不必要,因为点集不会很大
|
|
for( i = 0; i < startEnds.length; i++) {
|
|
for( j = 0; j < endEnds.length; j++) {
|
|
distance = Math.abs(startEnds[i].x - endEnds[j].x) + Math.abs(startEnds[i].y - endEnds[j].y) * 0.5; //Vector.fromPoints( startEnds[i], endEnds[j] ).length();
|
|
if(distance < minDistance) {
|
|
minDistance = distance;
|
|
nearStart = startEnds[i];
|
|
nearEnd = endEnds[j];
|
|
}
|
|
}
|
|
}
|
|
return {
|
|
start: new Vector(nearStart.x, nearStart.y),
|
|
end: new Vector(nearEnd.x, nearEnd.y)
|
|
};
|
|
},
|
|
updateConnection: function() {
|
|
if(!this.isReady()) {
|
|
return false;
|
|
}
|
|
var endPoints = this.calcEndPoints(),
|
|
startEnd = endPoints.start,
|
|
endEnd = endPoints.end;
|
|
|
|
fillNormal(startEnd);
|
|
fillNormal(endEnd);
|
|
|
|
var pointVector = Vector.fromPoints( startEnd, endEnd );
|
|
|
|
var forward = pointVector.project(startEnd.normal);
|
|
var backward = pointVector.reverse().project(endEnd.normal);
|
|
|
|
forward = startEnd.add(forward.multipy(0.5));
|
|
backward = endEnd.add(backward.multipy(0.5));
|
|
|
|
this.startBesierPoint.setVertex(startEnd.x, startEnd.y);
|
|
this.startBesierPoint.setForward(forward.x, forward.y);
|
|
|
|
this.endBesierPoint.setVertex(endEnd.x, endEnd.y);
|
|
this.endBesierPoint.setBackward(backward.x, backward.y);
|
|
}
|
|
});
|
|
});
|