CreateMoveSnapping.js 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. import SnapContext from './SnapContext';
  2. import {
  3. getChildren,
  4. isSnapped,
  5. mid
  6. } from './SnapUtil';
  7. import { isCmd } from '../keyboard/KeyboardUtil';
  8. import {
  9. forEach,
  10. isNumber
  11. } from 'min-dash';
  12. var HIGHER_PRIORITY = 1250;
  13. /**
  14. * Snap during create and move.
  15. *
  16. * @param {EventBus} elementRegistry
  17. * @param {EventBus} eventBus
  18. * @param {Snapping} snapping
  19. */
  20. export default function CreateMoveSnapping(elementRegistry, eventBus, snapping) {
  21. var self = this;
  22. this._elementRegistry = elementRegistry;
  23. eventBus.on([
  24. 'create.start',
  25. 'shape.move.start'
  26. ], function(event) {
  27. self.initSnap(event);
  28. });
  29. eventBus.on([
  30. 'create.move',
  31. 'create.end',
  32. 'shape.move.move',
  33. 'shape.move.end'
  34. ], HIGHER_PRIORITY, function(event) {
  35. var context = event.context,
  36. shape = context.shape,
  37. snapContext = context.snapContext,
  38. target = context.target;
  39. if (event.originalEvent && isCmd(event.originalEvent)) {
  40. return;
  41. }
  42. if (isSnapped(event) || !target) {
  43. return;
  44. }
  45. var snapPoints = snapContext.pointsForTarget(target);
  46. if (!snapPoints.initialized) {
  47. snapPoints = self.addSnapTargetPoints(snapPoints, shape, target);
  48. snapPoints.initialized = true;
  49. }
  50. snapping.snap(event, snapPoints);
  51. });
  52. eventBus.on([
  53. 'create.cleanup',
  54. 'shape.move.cleanup'
  55. ], function() {
  56. snapping.hide();
  57. });
  58. }
  59. CreateMoveSnapping.$inject = [
  60. 'elementRegistry',
  61. 'eventBus',
  62. 'snapping'
  63. ];
  64. CreateMoveSnapping.prototype.initSnap = function(event) {
  65. var elementRegistry = this._elementRegistry;
  66. var context = event.context,
  67. shape = context.shape,
  68. snapContext = context.snapContext;
  69. if (!snapContext) {
  70. snapContext = context.snapContext = new SnapContext();
  71. }
  72. var shapeMid;
  73. if (elementRegistry.get(shape.id)) {
  74. // move
  75. shapeMid = mid(shape, event);
  76. } else {
  77. // create
  78. shapeMid = {
  79. x: event.x + mid(shape).x,
  80. y: event.y + mid(shape).y
  81. };
  82. }
  83. var shapeTopLeft = {
  84. x: shapeMid.x - shape.width / 2,
  85. y: shapeMid.y - shape.height / 2
  86. },
  87. shapeBottomRight = {
  88. x: shapeMid.x + shape.width / 2,
  89. y: shapeMid.y + shape.height / 2
  90. };
  91. snapContext.setSnapOrigin('mid', {
  92. x: shapeMid.x - event.x,
  93. y: shapeMid.y - event.y
  94. });
  95. // snap labels to mid only
  96. if (isLabel(shape)) {
  97. return snapContext;
  98. }
  99. snapContext.setSnapOrigin('top-left', {
  100. x: shapeTopLeft.x - event.x,
  101. y: shapeTopLeft.y - event.y
  102. });
  103. snapContext.setSnapOrigin('bottom-right', {
  104. x: shapeBottomRight.x - event.x,
  105. y: shapeBottomRight.y - event.y
  106. });
  107. return snapContext;
  108. };
  109. CreateMoveSnapping.prototype.addSnapTargetPoints = function(snapPoints, shape, target) {
  110. var snapTargets = this.getSnapTargets(shape, target);
  111. forEach(snapTargets, function(snapTarget) {
  112. // handle labels
  113. if (isLabel(snapTarget)) {
  114. if (isLabel(shape)) {
  115. snapPoints.add('mid', mid(snapTarget));
  116. }
  117. return;
  118. }
  119. // handle connections
  120. if (isConnection(snapTarget)) {
  121. // ignore single segment connections
  122. if (snapTarget.waypoints.length < 3) {
  123. return;
  124. }
  125. // ignore first and last waypoint
  126. var waypoints = snapTarget.waypoints.slice(1, -1);
  127. forEach(waypoints, function(waypoint) {
  128. snapPoints.add('mid', waypoint);
  129. });
  130. return;
  131. }
  132. // handle shapes
  133. snapPoints.add('mid', mid(snapTarget));
  134. });
  135. if (!isNumber(shape.x) || !isNumber(shape.y)) {
  136. return snapPoints;
  137. }
  138. // snap to original position when moving
  139. if (this._elementRegistry.get(shape.id)) {
  140. snapPoints.add('mid', mid(shape));
  141. }
  142. return snapPoints;
  143. };
  144. CreateMoveSnapping.prototype.getSnapTargets = function(shape, target) {
  145. return getChildren(target).filter(function(child) {
  146. return !isHidden(child);
  147. });
  148. };
  149. // helpers //////////
  150. function isConnection(element) {
  151. return !!element.waypoints;
  152. }
  153. function isHidden(element) {
  154. return !!element.hidden;
  155. }
  156. function isLabel(element) {
  157. return !!element.labelTarget;
  158. }