GridSnapping.js 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. import {
  2. setSnapped,
  3. isSnapped
  4. } from '../snapping/SnapUtil';
  5. import { isCmd } from '../keyboard/KeyboardUtil';
  6. import { isNumber } from 'min-dash';
  7. var SPACING = 10,
  8. LOWER_PRIORITY = 1200;
  9. export default function GridSnapping(
  10. eventBus,
  11. config,
  12. grid
  13. ) {
  14. this._grid = grid;
  15. if (config) {
  16. this.active = config.active === false ? false : true;
  17. } else {
  18. this.active = true;
  19. }
  20. var self = this;
  21. eventBus.on('diagram.init', LOWER_PRIORITY, function() {
  22. self.setActive(self.active);
  23. if (!self.active) {
  24. grid.setVisible(false);
  25. }
  26. });
  27. eventBus.on([
  28. 'shape.move.move',
  29. 'shape.move.end',
  30. 'create.move',
  31. 'create.end',
  32. 'connect.move',
  33. 'connect.end',
  34. 'resize.move',
  35. 'resize.end',
  36. 'bendpoint.move.move',
  37. 'bendpoint.move.end',
  38. 'connectionSegment.move.move',
  39. 'connectionSegment.move.end'
  40. ], LOWER_PRIORITY, function(event) {
  41. var originalEvent = event.originalEvent;
  42. if (!self.active || (originalEvent && isCmd(originalEvent))) {
  43. return;
  44. }
  45. [ 'x', 'y' ].forEach(function(axis) {
  46. if (!isSnapped(event, axis)) {
  47. self.snap(event, axis);
  48. }
  49. });
  50. });
  51. }
  52. GridSnapping.prototype.snap = function(event, axis) {
  53. var snapConstraints = getSnapConstraints(event, axis);
  54. var snappedValue = this._getSnappedValue(event[ axis ], snapConstraints);
  55. setSnapped(event, axis, snappedValue);
  56. };
  57. GridSnapping.prototype._getSnappedValue = function(value, snapConstraints) {
  58. value = quantize(value, SPACING);
  59. var min, max;
  60. if (snapConstraints) {
  61. min = snapConstraints.min;
  62. max = snapConstraints.max;
  63. if (isNumber(min)) {
  64. min = quantize(min, SPACING, 'ceil');
  65. value = Math.max(value, min);
  66. }
  67. if (isNumber(max)) {
  68. max = quantize(max, SPACING, 'floor');
  69. value = Math.min(value, max);
  70. }
  71. }
  72. return value;
  73. };
  74. GridSnapping.prototype.isActive = function() {
  75. return this.active;
  76. };
  77. GridSnapping.prototype.setActive = function(active) {
  78. this.active = active;
  79. };
  80. GridSnapping.prototype.toggleActive = function() {
  81. this.setActive(!this.active);
  82. };
  83. GridSnapping.$inject = [
  84. 'eventBus',
  85. 'config.gridSnapping',
  86. 'grid'
  87. ];
  88. // helpers //////////
  89. /**
  90. * Get minimum and maximum snap constraints.
  91. *
  92. * @param {Object} event - Event.
  93. * @param {String} axis - Axis.
  94. *
  95. * @returns {Object}
  96. */
  97. function getSnapConstraints(event, axis) {
  98. var context = event.context,
  99. resizeConstraints = context.resizeConstraints;
  100. if (!resizeConstraints) {
  101. return null;
  102. }
  103. var direction = context.direction;
  104. var minResizeConstraints = resizeConstraints.min,
  105. maxResizeConstraints = resizeConstraints.max;
  106. var snapConstraints = {};
  107. // resize
  108. if (minResizeConstraints) {
  109. if (isHorizontal(axis)) {
  110. if (isWest(direction)) {
  111. snapConstraints.max = minResizeConstraints.left;
  112. } else {
  113. snapConstraints.min = minResizeConstraints.right;
  114. }
  115. } else {
  116. if (isNorth(direction)) {
  117. snapConstraints.max = minResizeConstraints.top;
  118. } else {
  119. snapConstraints.min = minResizeConstraints.bottom;
  120. }
  121. }
  122. }
  123. if (maxResizeConstraints) {
  124. if (isHorizontal(axis)) {
  125. if (isWest(direction)) {
  126. snapConstraints.min = maxResizeConstraints.left;
  127. } else {
  128. snapConstraints.max = maxResizeConstraints.right;
  129. }
  130. } else {
  131. if (isNorth(direction)) {
  132. snapConstraints.min = maxResizeConstraints.top;
  133. } else {
  134. snapConstraints.max = maxResizeConstraints.bottom;
  135. }
  136. }
  137. }
  138. return snapConstraints;
  139. }
  140. function isHorizontal(axis) {
  141. return axis === 'x';
  142. }
  143. function isNorth(direction) {
  144. return direction.charAt(0) === 'n';
  145. }
  146. function isWest(direction) {
  147. return direction.charAt(1) === 'w';
  148. }
  149. function quantize(value, quantum, fn) {
  150. if (!fn) {
  151. fn = 'round';
  152. }
  153. return Math[ fn ](value / quantum) * quantum;
  154. }