sizeHelpers.ts 2.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. import { ExcalidrawElement, MutableExcalidrawElement } from "./types";
  2. import { invalidateShapeForElement } from "../renderer/renderElement";
  3. import { mutateElement } from "./mutateElement";
  4. export function isInvisiblySmallElement(element: ExcalidrawElement): boolean {
  5. if (element.type === "arrow" || element.type === "line") {
  6. return element.points.length < 2;
  7. }
  8. return element.width === 0 && element.height === 0;
  9. }
  10. /**
  11. * Makes a perfect shape or diagonal/horizontal/vertical line
  12. */
  13. export function getPerfectElementSize(
  14. elementType: string,
  15. width: number,
  16. height: number,
  17. ): { width: number; height: number } {
  18. const absWidth = Math.abs(width);
  19. const absHeight = Math.abs(height);
  20. if (elementType === "line" || elementType === "arrow") {
  21. if (absHeight < absWidth / 2) {
  22. height = 0;
  23. } else if (absWidth < absHeight / 2) {
  24. width = 0;
  25. } else {
  26. height = absWidth * Math.sign(height);
  27. }
  28. } else if (elementType !== "selection") {
  29. height = absWidth * Math.sign(height);
  30. }
  31. return { width, height };
  32. }
  33. export function resizePerfectLineForNWHandler(
  34. element: MutableExcalidrawElement,
  35. x: number,
  36. y: number,
  37. ) {
  38. const anchorX = element.x + element.width;
  39. const anchorY = element.y + element.height;
  40. const distanceToAnchorX = x - anchorX;
  41. const distanceToAnchorY = y - anchorY;
  42. if (Math.abs(distanceToAnchorX) < Math.abs(distanceToAnchorY) / 2) {
  43. element.x = anchorX;
  44. element.width = 0;
  45. element.y = y;
  46. element.height = -distanceToAnchorY;
  47. } else if (Math.abs(distanceToAnchorY) < Math.abs(element.width) / 2) {
  48. element.y = anchorY;
  49. element.height = 0;
  50. } else {
  51. element.x = x;
  52. element.width = -distanceToAnchorX;
  53. element.height =
  54. Math.sign(distanceToAnchorY) *
  55. Math.sign(distanceToAnchorX) *
  56. element.width;
  57. element.y = anchorY - element.height;
  58. }
  59. }
  60. /**
  61. * @returns {boolean} whether element was normalized
  62. */
  63. export function normalizeDimensions(
  64. element: ExcalidrawElement | null,
  65. ): element is ExcalidrawElement {
  66. if (
  67. !element ||
  68. (element.width >= 0 && element.height >= 0) ||
  69. element.type === "line" ||
  70. element.type === "arrow"
  71. ) {
  72. return false;
  73. }
  74. if (element.width < 0) {
  75. mutateElement(element, element => {
  76. element.width = Math.abs(element.width);
  77. element.x -= element.width;
  78. });
  79. }
  80. if (element.height < 0) {
  81. mutateElement(element, element => {
  82. element.height = Math.abs(element.height);
  83. element.y -= element.height;
  84. });
  85. }
  86. invalidateShapeForElement(element);
  87. return true;
  88. }