bezierconnection.js 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. define(function (require, exports, module) {
  2. var Bezier = require('graphic/bezier');
  3. var BezierPoint = require('graphic/bezierpoint');
  4. var Vector = require('graphic/vector');
  5. var Pen = require('graphic/pen');
  6. function mid(a, b) {
  7. return (a + b) / 2;
  8. }
  9. function getSnapPoints( snaper ) {
  10. if(snaper.getSnapPoints) {
  11. return snaper.getSnapPoints();
  12. }
  13. var box = snaper.getRenderBox();
  14. var x1 = box.x, x2 = box.x + box.width,
  15. y1 = box.y, y2 = box.y + box.height,
  16. xm = mid(x1, x2), ym = mid(y1, y2);
  17. return [
  18. { x: xm, y: y1, type: 'top' }, // top
  19. { x: x2, y: ym, type: 'right' }, // right
  20. { x: xm, y: y2, type: 'bottom' }, // bottom
  21. { x: x1, y: ym, type: 'left' } // left
  22. ];
  23. }
  24. var DIR_NORMALS = {
  25. top: new Vector(0, -1),
  26. left: new Vector(-1, 0),
  27. bottom: new Vector(0, 1),
  28. right: new Vector(1, 0)
  29. };
  30. function fillNormal( snapPoint ) {
  31. if(snapPoint.normal) {
  32. return;
  33. }
  34. snapPoint.normal = DIR_NORMALS[snapPoint.type] || DIR_NORMALS.left;
  35. }
  36. return require('core/class').createClass("SnapCurve", {
  37. base: Bezier,
  38. constructor: function( start, end ) {
  39. this.callBase();
  40. this.setStartSnaper( start );
  41. this.setEndSnaper( end );
  42. this.init();
  43. this.updateConnection();
  44. },
  45. init: function() {
  46. this.addPoint(this.startBesierPoint = new BezierPoint());
  47. this.addPoint(this.endBesierPoint = new BezierPoint());
  48. this.stroke(new Pen('red', 3));
  49. },
  50. bindSnaper: function( snaper ) {
  51. var me = this;
  52. snaper.on('shapeupdate', function() {
  53. me.updateConnection();
  54. });
  55. },
  56. setStartSnaper: function( snaper ) {
  57. this.start = snaper;
  58. this.bindSnaper(snaper);
  59. },
  60. setEndSnaper: function( snaper ) {
  61. this.end = snaper;
  62. this.bindSnaper(snaper);
  63. },
  64. isReady: function() {
  65. return !!(this.start && this.end);
  66. },
  67. calcEndPoints: function() {
  68. var startEnds = getSnapPoints(this.start),
  69. endEnds = getSnapPoints(this.end);
  70. var nearStart, nearEnd, minDistance = Number.MAX_VALUE;
  71. var i, j, startEnd, endEnd, distance;
  72. // 寻找最近的粘附点
  73. // 暴力解法:可优化但不必要,因为点集不会很大
  74. for( i = 0; i < startEnds.length; i++) {
  75. for( j = 0; j < endEnds.length; j++) {
  76. 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();
  77. if(distance < minDistance) {
  78. minDistance = distance;
  79. nearStart = startEnds[i];
  80. nearEnd = endEnds[j];
  81. }
  82. }
  83. }
  84. return {
  85. start: new Vector(nearStart.x, nearStart.y),
  86. end: new Vector(nearEnd.x, nearEnd.y)
  87. };
  88. },
  89. updateConnection: function() {
  90. if(!this.isReady()) {
  91. return false;
  92. }
  93. var endPoints = this.calcEndPoints(),
  94. startEnd = endPoints.start,
  95. endEnd = endPoints.end;
  96. fillNormal(startEnd);
  97. fillNormal(endEnd);
  98. var pointVector = Vector.fromPoints( startEnd, endEnd );
  99. var forward = pointVector.project(startEnd.normal);
  100. var backward = pointVector.reverse().project(endEnd.normal);
  101. forward = startEnd.add(forward.multipy(0.5));
  102. backward = endEnd.add(backward.multipy(0.5));
  103. this.startBesierPoint.setVertex(startEnd.x, startEnd.y);
  104. this.startBesierPoint.setForward(forward.x, forward.y);
  105. this.endBesierPoint.setVertex(endEnd.x, endEnd.y);
  106. this.endBesierPoint.setBackward(backward.x, backward.y);
  107. }
  108. });
  109. });