SnapUtil.js 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. var abs = Math.abs,
  2. round = Math.round;
  3. /**
  4. * Snap value to a collection of reference values.
  5. *
  6. * @param {number} value
  7. * @param {Array<number>} values
  8. * @param {number} [tolerance=10]
  9. *
  10. * @return {number} the value we snapped to or null, if none snapped
  11. */
  12. export function snapTo(value, values, tolerance) {
  13. tolerance = tolerance === undefined ? 10 : tolerance;
  14. var idx, snapValue;
  15. for (idx = 0; idx < values.length; idx++) {
  16. snapValue = values[idx];
  17. if (abs(snapValue - value) <= tolerance) {
  18. return snapValue;
  19. }
  20. }
  21. }
  22. export function topLeft(bounds) {
  23. return {
  24. x: bounds.x,
  25. y: bounds.y
  26. };
  27. }
  28. export function topRight(bounds) {
  29. return {
  30. x: bounds.x + bounds.width,
  31. y: bounds.y
  32. };
  33. }
  34. export function bottomLeft(bounds) {
  35. return {
  36. x: bounds.x,
  37. y: bounds.y + bounds.height
  38. };
  39. }
  40. export function bottomRight(bounds) {
  41. return {
  42. x: bounds.x + bounds.width,
  43. y: bounds.y + bounds.height
  44. };
  45. }
  46. export function mid(bounds, defaultValue) {
  47. if (!bounds || isNaN(bounds.x) || isNaN(bounds.y)) {
  48. return defaultValue;
  49. }
  50. return {
  51. x: round(bounds.x + bounds.width / 2),
  52. y: round(bounds.y + bounds.height / 2)
  53. };
  54. }
  55. /**
  56. * Retrieve the snap state of the given event.
  57. *
  58. * @param {Event} event
  59. * @param {string} axis
  60. *
  61. * @return {boolean} the snapped state
  62. *
  63. */
  64. export function isSnapped(event, axis) {
  65. var snapped = event.snapped;
  66. if (!snapped) {
  67. return false;
  68. }
  69. if (typeof axis === 'string') {
  70. return snapped[axis];
  71. }
  72. return snapped.x && snapped.y;
  73. }
  74. /**
  75. * Set the given event as snapped.
  76. *
  77. * This method may change the x and/or y position of the shape
  78. * from the given event!
  79. *
  80. * @param {Event} event
  81. * @param {string} axis
  82. * @param {number|boolean} value
  83. *
  84. * @return {number} old value
  85. */
  86. export function setSnapped(event, axis, value) {
  87. if (typeof axis !== 'string') {
  88. throw new Error('axis must be in [x, y]');
  89. }
  90. if (typeof value !== 'number' && value !== false) {
  91. throw new Error('value must be Number or false');
  92. }
  93. var delta,
  94. previousValue = event[axis];
  95. var snapped = event.snapped = (event.snapped || {});
  96. if (value === false) {
  97. snapped[axis] = false;
  98. } else {
  99. snapped[axis] = true;
  100. delta = value - previousValue;
  101. event[axis] += delta;
  102. event['d' + axis] += delta;
  103. }
  104. return previousValue;
  105. }
  106. /**
  107. * Get children of a shape.
  108. *
  109. * @param {djs.model.Shape} parent
  110. *
  111. * @returns {Array<djs.model.Shape|djs.model.Connection>}
  112. */
  113. export function getChildren(parent) {
  114. return parent.children || [];
  115. }