useDragBox.ts 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. import { ref, onMounted, onUnmounted, nextTick } from "vue";
  2. export const useDragBox = () => {
  3. const dragBox = ref({
  4. top: 0,
  5. left: 0,
  6. pos1: 0,
  7. pos2: 0,
  8. pos3: 0,
  9. pos4: 0,
  10. width: 400,
  11. height: 50,
  12. initial: {
  13. top: 0,
  14. left: 0
  15. },
  16. latest: {
  17. top: null,
  18. left: null
  19. },
  20. debounceTimeout: null,
  21. lastTappedDate: 0
  22. });
  23. const onDragBoxUpdate = ref();
  24. const setOnDragBoxUpdate = newOnDragBoxUpdate => {
  25. onDragBoxUpdate.value = newOnDragBoxUpdate;
  26. };
  27. const setInitialBox = (initial, reset = false) => {
  28. dragBox.value.initial = initial || dragBox.value.initial;
  29. if (reset)
  30. dragBox.value = { ...dragBox.value, ...dragBox.value.initial };
  31. };
  32. const resetBoxPosition = (preventUpdate = false) => {
  33. setInitialBox(null, true);
  34. dragBox.value.latest.top = dragBox.value.top;
  35. dragBox.value.latest.left = dragBox.value.left;
  36. if (!preventUpdate && typeof onDragBoxUpdate.value === "function")
  37. onDragBoxUpdate.value();
  38. };
  39. const onDragBox = e => {
  40. const e1 = e || window.event;
  41. const e1IsTouch = e1.type === "touchstart";
  42. e1.preventDefault();
  43. if (e1IsTouch) {
  44. // Handle double click from touch (if this method is twice in a row within one second)
  45. if (Date.now() - dragBox.value.lastTappedDate <= 1000) {
  46. resetBoxPosition();
  47. dragBox.value.lastTappedDate = 0;
  48. return;
  49. }
  50. dragBox.value.lastTappedDate = Date.now();
  51. }
  52. dragBox.value.pos3 = e1IsTouch
  53. ? e1.changedTouches[0].clientX
  54. : e1.clientX;
  55. dragBox.value.pos4 = e1IsTouch
  56. ? e1.changedTouches[0].clientY
  57. : e1.clientY;
  58. const onMove = e => {
  59. const e2 = e || window.event;
  60. const e2IsTouch = e2.type === "touchmove";
  61. if (!e2IsTouch) e2.preventDefault();
  62. // Get the clientX and clientY
  63. const e2ClientX = e2IsTouch
  64. ? e2.changedTouches[0].clientX
  65. : e2.clientX;
  66. const e2ClientY = e2IsTouch
  67. ? e2.changedTouches[0].clientY
  68. : e2.clientY;
  69. // calculate the new cursor position:
  70. dragBox.value.pos1 = dragBox.value.pos3 - e2ClientX;
  71. dragBox.value.pos2 = dragBox.value.pos4 - e2ClientY;
  72. dragBox.value.pos3 = e2ClientX;
  73. dragBox.value.pos4 = e2ClientY;
  74. // set the element's new position:
  75. dragBox.value.top -= dragBox.value.pos2;
  76. dragBox.value.left -= dragBox.value.pos1;
  77. if (
  78. dragBox.value.top >
  79. document.body.clientHeight - dragBox.value.height
  80. )
  81. dragBox.value.top =
  82. document.body.clientHeight - dragBox.value.height;
  83. if (dragBox.value.top < 0) dragBox.value.top = 0;
  84. if (
  85. dragBox.value.left >
  86. document.body.clientWidth - dragBox.value.width
  87. )
  88. dragBox.value.left =
  89. document.body.clientWidth - dragBox.value.width;
  90. if (dragBox.value.left < 0) dragBox.value.left = 0;
  91. };
  92. document.onmousemove = onMove;
  93. document.ontouchmove = onMove;
  94. const onUp = () => {
  95. document.onmouseup = null;
  96. document.ontouchend = null;
  97. document.onmousemove = null;
  98. document.ontouchmove = null;
  99. if (typeof onDragBoxUpdate.value === "function")
  100. onDragBoxUpdate.value();
  101. };
  102. document.onmouseup = onUp;
  103. document.ontouchend = onUp;
  104. };
  105. const onWindowResizeDragBox = () => {
  106. if (dragBox.value.debounceTimeout)
  107. clearTimeout(dragBox.value.debounceTimeout);
  108. dragBox.value.debounceTimeout = setTimeout(() => {
  109. if (
  110. dragBox.value.top === dragBox.value.latest.top &&
  111. dragBox.value.left === dragBox.value.latest.left
  112. ) {
  113. resetBoxPosition();
  114. } else {
  115. if (
  116. dragBox.value.top >
  117. document.body.clientHeight - dragBox.value.height
  118. )
  119. dragBox.value.top =
  120. document.body.clientHeight - dragBox.value.height;
  121. if (dragBox.value.top < 0) dragBox.value.top = 0;
  122. if (
  123. dragBox.value.left >
  124. document.body.clientWidth - dragBox.value.width
  125. )
  126. dragBox.value.left =
  127. document.body.clientWidth - dragBox.value.width;
  128. if (dragBox.value.left < 0) dragBox.value.left = 0;
  129. if (typeof onDragBoxUpdate.value === "function")
  130. onDragBoxUpdate.value();
  131. }
  132. }, 50);
  133. };
  134. onMounted(async () => {
  135. resetBoxPosition(true);
  136. await nextTick();
  137. onWindowResizeDragBox();
  138. window.addEventListener("resize", onWindowResizeDragBox);
  139. });
  140. onUnmounted(() => {
  141. window.removeEventListener("resize", onWindowResizeDragBox);
  142. if (dragBox.value.debounceTimeout)
  143. clearTimeout(dragBox.value.debounceTimeout);
  144. });
  145. return {
  146. dragBox,
  147. setInitialBox,
  148. onDragBox,
  149. resetBoxPosition,
  150. onWindowResizeDragBox,
  151. setOnDragBoxUpdate
  152. };
  153. };