AttachUtil.js 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. import {
  2. asTRBL,
  3. getOrientation,
  4. roundPoint
  5. } from '../layout/LayoutUtil';
  6. import {
  7. center,
  8. delta
  9. } from './PositionUtil';
  10. /**
  11. * Calculates the absolute point relative to the new element's position
  12. *
  13. * @param {point} point [absolute]
  14. * @param {bounds} oldBounds
  15. * @param {bounds} newBounds
  16. *
  17. * @return {point} point [absolute]
  18. */
  19. export function getNewAttachPoint(point, oldBounds, newBounds) {
  20. var oldCenter = center(oldBounds),
  21. newCenter = center(newBounds),
  22. oldDelta = delta(point, oldCenter);
  23. var newDelta = {
  24. x: oldDelta.x * (newBounds.width / oldBounds.width),
  25. y: oldDelta.y * (newBounds.height / oldBounds.height)
  26. };
  27. return roundPoint({
  28. x: newCenter.x + newDelta.x,
  29. y: newCenter.y + newDelta.y
  30. });
  31. }
  32. /**
  33. * Calculates the shape's delta relative to a new position
  34. * of a certain element's bounds
  35. *
  36. * @param {djs.model.Shape} point [absolute]
  37. * @param {bounds} oldBounds
  38. * @param {bounds} newBounds
  39. *
  40. * @return {delta} delta
  41. */
  42. export function getNewAttachShapeDelta(shape, oldBounds, newBounds) {
  43. var shapeCenter = center(shape),
  44. oldCenter = center(oldBounds),
  45. newCenter = center(newBounds),
  46. shapeDelta = delta(shape, shapeCenter),
  47. oldCenterDelta = delta(shapeCenter, oldCenter),
  48. stickyPositionDelta = getStickyPositionDelta(shapeCenter, oldBounds, newBounds);
  49. if (stickyPositionDelta) {
  50. return stickyPositionDelta;
  51. }
  52. var newCenterDelta = {
  53. x: oldCenterDelta.x * (newBounds.width / oldBounds.width),
  54. y: oldCenterDelta.y * (newBounds.height / oldBounds.height)
  55. };
  56. var newShapeCenter = {
  57. x: newCenter.x + newCenterDelta.x,
  58. y: newCenter.y + newCenterDelta.y
  59. };
  60. return roundPoint({
  61. x: newShapeCenter.x + shapeDelta.x - shape.x,
  62. y: newShapeCenter.y + shapeDelta.y - shape.y
  63. });
  64. }
  65. function getStickyPositionDelta(oldShapeCenter, oldBounds, newBounds) {
  66. var oldTRBL = asTRBL(oldBounds),
  67. newTRBL = asTRBL(newBounds);
  68. if (isMoved(oldTRBL, newTRBL)) {
  69. return null;
  70. }
  71. var oldOrientation = getOrientation(oldBounds, oldShapeCenter),
  72. stickyPositionDelta,
  73. newShapeCenter,
  74. newOrientation;
  75. if (oldOrientation === 'top') {
  76. stickyPositionDelta = {
  77. x: 0,
  78. y: newTRBL.bottom - oldTRBL.bottom
  79. };
  80. } else if (oldOrientation === 'bottom') {
  81. stickyPositionDelta = {
  82. x: 0,
  83. y: newTRBL.top - oldTRBL.top
  84. };
  85. } else if (oldOrientation === 'right') {
  86. stickyPositionDelta = {
  87. x: newTRBL.left - oldTRBL.left,
  88. y: 0
  89. };
  90. } else if (oldOrientation === 'left') {
  91. stickyPositionDelta = {
  92. x: newTRBL.right - oldTRBL.right,
  93. y: 0
  94. };
  95. } else {
  96. // fallback to proportional movement for corner-placed attachments
  97. return null;
  98. }
  99. newShapeCenter = {
  100. x: oldShapeCenter.x + stickyPositionDelta.x,
  101. y: oldShapeCenter.y + stickyPositionDelta.y
  102. };
  103. newOrientation = getOrientation(newBounds, newShapeCenter);
  104. if (newOrientation !== oldOrientation) {
  105. // fallback to proportional movement if orientation would otherwise change
  106. return null;
  107. }
  108. return stickyPositionDelta;
  109. }
  110. function isMoved(oldTRBL, newTRBL) {
  111. return isHorizontallyMoved(oldTRBL, newTRBL) || isVerticallyMoved(oldTRBL, newTRBL);
  112. }
  113. function isHorizontallyMoved(oldTRBL, newTRBL) {
  114. return oldTRBL.right !== newTRBL.right && oldTRBL.left !== newTRBL.left;
  115. }
  116. function isVerticallyMoved(oldTRBL, newTRBL) {
  117. return oldTRBL.top !== newTRBL.top && oldTRBL.bottom !== newTRBL.bottom;
  118. }