| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116 | 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);        }    });});
 |