useDragBox.ts 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. import { ref, onMounted, onUnmounted, nextTick } from "vue";
  2. export default function 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. document.onmousemove = document.ontouchmove = 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.onmouseup = document.ontouchend = () => {
  93. document.onmouseup = null;
  94. document.ontouchend = null;
  95. document.onmousemove = null;
  96. document.ontouchmove = null;
  97. if (typeof onDragBoxUpdate.value === "function")
  98. onDragBoxUpdate.value();
  99. };
  100. };
  101. const onWindowResizeDragBox = () => {
  102. if (dragBox.value.debounceTimeout)
  103. clearTimeout(dragBox.value.debounceTimeout);
  104. dragBox.value.debounceTimeout = setTimeout(() => {
  105. if (
  106. dragBox.value.top === dragBox.value.latest.top &&
  107. dragBox.value.left === dragBox.value.latest.left
  108. ) {
  109. resetBoxPosition();
  110. } else {
  111. if (
  112. dragBox.value.top >
  113. document.body.clientHeight - dragBox.value.height
  114. )
  115. dragBox.value.top =
  116. document.body.clientHeight - dragBox.value.height;
  117. if (dragBox.value.top < 0) dragBox.value.top = 0;
  118. if (
  119. dragBox.value.left >
  120. document.body.clientWidth - dragBox.value.width
  121. )
  122. dragBox.value.left =
  123. document.body.clientWidth - dragBox.value.width;
  124. if (dragBox.value.left < 0) dragBox.value.left = 0;
  125. if (typeof onDragBoxUpdate.value === "function")
  126. onDragBoxUpdate.value();
  127. }
  128. }, 50);
  129. };
  130. onMounted(async () => {
  131. resetBoxPosition(true);
  132. await nextTick();
  133. onWindowResizeDragBox();
  134. window.addEventListener("resize", onWindowResizeDragBox);
  135. });
  136. onUnmounted(() => {
  137. window.removeEventListener("resize", onWindowResizeDragBox);
  138. if (dragBox.value.debounceTimeout)
  139. clearTimeout(dragBox.value.debounceTimeout);
  140. });
  141. return {
  142. dragBox,
  143. setInitialBox,
  144. onDragBox,
  145. resetBoxPosition,
  146. onWindowResizeDragBox,
  147. setOnDragBoxUpdate
  148. };
  149. }