index.vue 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. <template>
  2. <div class="drag-container" v-show="show">
  3. <slot />
  4. </div>
  5. </template>
  6. <script lang="ts">
  7. import {
  8. defineComponent,
  9. reactive,
  10. toRefs,
  11. onMounted,
  12. watch,
  13. watchEffect
  14. } from 'vue';
  15. export default defineComponent({
  16. props: {
  17. show: {
  18. type: Boolean,
  19. default: () => false
  20. },
  21. domClassName: {
  22. type: String,
  23. default: ''
  24. }
  25. },
  26. setup(props: any, ctx: any) {
  27. const data = reactive({
  28. show: false,
  29. domClassName: '',
  30. startPosition: {
  31. left: '',
  32. top: '',
  33. cssText: ''
  34. }
  35. });
  36. watchEffect(() => {
  37. data.show = props.show;
  38. data.domClassName = props.domClassName;
  39. });
  40. onMounted(() => {
  41. const dragDom = document.getElementsByClassName(
  42. props.domClassName ? props.domClassName : 'drag-container'
  43. )[0] as HTMLElement;
  44. if (!dragDom) return;
  45. let isDrag = false;
  46. watch(
  47. () => data.show,
  48. (newVal, oldVal) => {
  49. data.show = newVal;
  50. if (newVal === oldVal) return;
  51. if (data.show === true) {
  52. dragDom.style.left = data.startPosition?.left;
  53. dragDom.style.top = data.startPosition?.top;
  54. dragDom.style.cssText = data.startPosition?.cssText;
  55. }
  56. }
  57. );
  58. const mouseDown = (e: MouseEvent) => {
  59. isDrag = true;
  60. const X = e.clientX - dragDom.offsetLeft;
  61. const Y = e.clientY - dragDom.offsetTop;
  62. const move = (e: MouseEvent) => {
  63. e.preventDefault();
  64. if (isDrag) {
  65. dragDom.style.left = `${e.clientX - X}Px`;
  66. dragDom.style.top = `${e.clientY - Y}Px`;
  67. }
  68. };
  69. document.addEventListener('mousemove', throttle(move, 20), false);
  70. document.addEventListener('mouseup', () => {
  71. isDrag = false;
  72. document.removeEventListener('mousemove', move);
  73. });
  74. };
  75. dragDom.addEventListener('mousedown', mouseDown);
  76. });
  77. function throttle(
  78. fn: { (e: MouseEvent): void; apply?: any },
  79. timer: number
  80. ) {
  81. let initTime = 0;
  82. return function (...args: any) {
  83. const nowTime = +new Date();
  84. if (nowTime - initTime > timer) {
  85. initTime = nowTime;
  86. fn.apply(ctx, args);
  87. }
  88. };
  89. }
  90. const positionReset = () => {
  91. const dragDom = document.getElementsByClassName(
  92. props.domClassName ? props.domClassName : 'drag-container'
  93. )[0] as HTMLElement;
  94. data.startPosition = {
  95. left: '',
  96. top: '',
  97. cssText: ''
  98. };
  99. dragDom.style.left = data.startPosition?.left;
  100. dragDom.style.top = data.startPosition?.top;
  101. dragDom.style.cssText = data.startPosition?.cssText;
  102. };
  103. ctx.expose({
  104. positionReset
  105. });
  106. return {
  107. ...toRefs(data),
  108. throttle
  109. };
  110. }
  111. });
  112. </script>
  113. <style lang="scss" scoped>
  114. @import url('../../styles/common.scss');
  115. @import url('../../styles/icon.scss');
  116. .drag-container {
  117. position: fixed;
  118. z-index: 100;
  119. }
  120. </style>