index.ts 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. // 弹窗拖动
  2. import { ref, Ref, watch, nextTick, computed } from 'vue';
  3. type posType = {
  4. top: number;
  5. left: number;
  6. };
  7. /**
  8. * @params classList 可拖动地方的class值,也为唯一值
  9. * @params boxClass 容器class值必须为唯一值,这个class和useid拼接 作为缓存主键
  10. * @params dragShow 弹窗是否显示
  11. * @params userId 当前用户id
  12. */
  13. export default function useDrag(
  14. classList: string[],
  15. boxClass: string,
  16. dragShow: Ref<boolean>,
  17. userId: string
  18. ) {
  19. const pos = ref<posType>({
  20. top: -1, // -1 为初始值 代表没有缓存 默认居中
  21. left: -1
  22. });
  23. const useIdDargClass = userId + boxClass;
  24. watch(dragShow, () => {
  25. if (dragShow.value) {
  26. // 初始化pos值
  27. initPos();
  28. window.addEventListener('resize', refreshPos);
  29. nextTick(() => {
  30. const boxClassDom = document.querySelector(
  31. `.${boxClass}`
  32. ) as HTMLElement;
  33. if (!boxClassDom) {
  34. return;
  35. }
  36. classList.map((className: string) => {
  37. const classDom = document.querySelector(
  38. `.${className}`
  39. ) as HTMLElement;
  40. if (classDom) {
  41. classDom.style.cursor = 'move';
  42. drag(classDom, boxClassDom, pos);
  43. }
  44. });
  45. });
  46. } else {
  47. window.removeEventListener('resize', refreshPos);
  48. setCachePos(useIdDargClass, pos.value);
  49. }
  50. });
  51. const styleDrag = computed(() => {
  52. // 没有设置拖动的时候保持原本的
  53. return pos.value.left === -1 && pos.value.top === -1
  54. ? {}
  55. : {
  56. position: 'fixed',
  57. left: `${pos.value.left}px`,
  58. top: `${pos.value.top}px`
  59. };
  60. });
  61. function initPos() {
  62. const posCache = getCachePos(useIdDargClass);
  63. // 有缓存 用缓存的值,没有缓存用默认
  64. if (posCache) {
  65. pos.value = posCache;
  66. nextTick(() => {
  67. const _itme = setTimeout(() => {
  68. clearTimeout(_itme);
  69. refreshPos();
  70. }, 300);
  71. });
  72. }
  73. }
  74. function refreshPos() {
  75. if (pos.value.left === -1 && pos.value.top === -1) {
  76. return;
  77. }
  78. const boxClassDom = document.querySelector(`.${boxClass}`) as HTMLElement;
  79. if (!boxClassDom) return;
  80. const parentElementRect = boxClassDom.getBoundingClientRect();
  81. const clientWidth = document.documentElement.clientWidth;
  82. const clientHeight = document.documentElement.clientHeight;
  83. const { top, left } = pos.value;
  84. const maxLeft = clientWidth - parentElementRect.width;
  85. const maxTop = clientHeight - parentElementRect.height;
  86. let moveX = left;
  87. let moveY = top;
  88. const minLeft = 0;
  89. const minTop = 0;
  90. moveX = moveX < minLeft ? minLeft : moveX > maxLeft ? maxLeft : moveX;
  91. moveY = moveY < minTop ? minTop : moveY > maxTop ? maxTop : moveY;
  92. pos.value = {
  93. top: moveY,
  94. left: moveX
  95. };
  96. }
  97. return {
  98. pos,
  99. styleDrag
  100. };
  101. }
  102. // 拖动
  103. function drag(el: HTMLElement, parentElement: HTMLElement, pos: Ref<posType>) {
  104. function mousedown(e: MouseEvent) {
  105. const parentElementRect = parentElement.getBoundingClientRect();
  106. const downX = e.clientX;
  107. const downY = e.clientY;
  108. const clientWidth = document.documentElement.clientWidth;
  109. const clientHeight = document.documentElement.clientHeight;
  110. const maxLeft = clientWidth - parentElementRect.width;
  111. const maxTop = clientHeight - parentElementRect.height;
  112. const minLeft = 0;
  113. const minTop = 0;
  114. function onMousemove(e: MouseEvent) {
  115. let moveX = parentElementRect.left + (e.clientX - downX);
  116. let moveY = parentElementRect.top + (e.clientY - downY);
  117. moveX = moveX < minLeft ? minLeft : moveX > maxLeft ? maxLeft : moveX;
  118. moveY = moveY < minTop ? minTop : moveY > maxTop ? maxTop : moveY;
  119. pos.value = {
  120. top: moveY,
  121. left: moveX
  122. };
  123. }
  124. function onMouseup() {
  125. document.removeEventListener('mousemove', onMousemove);
  126. document.removeEventListener('mouseup', onMouseup);
  127. }
  128. document.addEventListener('mousemove', onMousemove);
  129. document.addEventListener('mouseup', onMouseup);
  130. }
  131. el.addEventListener('mousedown', mousedown);
  132. }
  133. // 缓存
  134. const localStorageName = 'dragCachePos';
  135. function getCachePos(useIdDargClass: string): null | undefined | posType {
  136. const localCachePos = localStorage.getItem(localStorageName);
  137. if (localCachePos) {
  138. try {
  139. return JSON.parse(localCachePos)[useIdDargClass];
  140. } catch {
  141. return null;
  142. }
  143. }
  144. return null;
  145. }
  146. function setCachePos(useIdDargClass: string, pos: posType) {
  147. const localCachePos = localStorage.getItem(localStorageName);
  148. let cachePosObj: Record<string, any> = {};
  149. if (localCachePos) {
  150. try {
  151. cachePosObj = JSON.parse(localCachePos);
  152. } catch {
  153. //
  154. }
  155. }
  156. cachePosObj[useIdDargClass] = pos;
  157. localStorage.setItem(localStorageName, JSON.stringify(cachePosObj));
  158. }