index.vue 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. <template>
  2. <view class="nut-drag" ref="myDrag" @touchstart="touchstart($event)">
  3. <slot></slot>
  4. </view>
  5. </template>
  6. <script lang="ts">
  7. import { onMounted, reactive, ref, watch } from 'vue';
  8. import { createComponent } from '@/utils/create';
  9. const { create } = createComponent('drag');
  10. export default create({
  11. props: {
  12. attract: {
  13. type: Boolean,
  14. default: false
  15. },
  16. direction: {
  17. type: String,
  18. default: 'all'
  19. },
  20. zIndex: {
  21. type: [Number, String],
  22. default: 11
  23. },
  24. boundary: {
  25. type: Object,
  26. default: function() {
  27. return {
  28. top: 0,
  29. left: 0,
  30. right: 0,
  31. bottom: 0
  32. };
  33. }
  34. }
  35. },
  36. setup(props: any, { emit }) {
  37. const myDrag = ref();
  38. console.log(props.direction);
  39. const state = reactive({
  40. elWidth: 0, // 元素的宽度
  41. elHeight: 0, // 元素的高度
  42. screenWidth: 0, // 屏幕的宽度
  43. screenHeight: 0, // 屏幕的高度
  44. startTop: 0, // 拖拽元素距离顶部的距离
  45. startLeft: 0, // 拖拽元素距离
  46. nx: 0,
  47. ny: 0,
  48. xPum: 0,
  49. yPum: 0,
  50. direction: props.direction,
  51. position: { x: 0, y: 0 },
  52. boundary: {
  53. top: 0,
  54. left: 0,
  55. right: 0,
  56. bottom: 0
  57. }
  58. });
  59. function getInfo() {
  60. const domElem = document.documentElement;
  61. state.elWidth = myDrag.value.offsetWidth;
  62. state.elHeight = myDrag.value.offsetHeight;
  63. state.screenWidth = domElem.clientWidth;
  64. state.screenHeight = domElem.clientHeight;
  65. console.log(
  66. domElem.clientWidth,
  67. domElem.clientHeight,
  68. myDrag.value.offsetWidth,
  69. domElem.offsetHeight
  70. );
  71. }
  72. function goLeft(target: any) {
  73. if (state.boundary.left) {
  74. if (target.style.left.split('px')[0] > state.boundary.left) {
  75. target.style.left = target.style.left.split('px')[0] - 10 + 'px';
  76. goLeft(target);
  77. } else {
  78. target.style.left = `${state.boundary.left}px`;
  79. }
  80. } else {
  81. if (target.style.left.split('px')[0] > 10) {
  82. target.style.left = target.style.left.split('px')[0] - 10 + 'px';
  83. goLeft(target);
  84. } else {
  85. target.style.left = '0px';
  86. }
  87. }
  88. }
  89. function goRight(target: any, rightLocation: any) {
  90. if (rightLocation - parseInt(target.style.left.split('px')[0]) > 10) {
  91. target.style.left =
  92. parseInt(target.style.left.split('px')[0]) + 10 + 'px';
  93. goRight(target, rightLocation);
  94. } else {
  95. target.style.left = rightLocation + 'px';
  96. }
  97. }
  98. function touchMove(e: any) {
  99. e.preventDefault();
  100. const target = e.currentTarget;
  101. if (e.targetTouches.length == 1) {
  102. const touch = e.targetTouches[0];
  103. state.nx = touch.clientX - state.position.x;
  104. state.ny = touch.clientY - state.position.y;
  105. state.xPum = state.startLeft + state.nx;
  106. state.yPum = state.startTop + state.ny;
  107. // console.log(state.xPum,state.yPum)
  108. const rightLocation =
  109. state.screenWidth - state.elWidth - state.boundary.right;
  110. // console.log(rightLocation)
  111. // 限制左右拖拽边界
  112. if (Math.abs(state.xPum) > rightLocation) {
  113. state.xPum = rightLocation;
  114. } else if (state.xPum <= state.boundary.left) {
  115. state.xPum = state.boundary.left;
  116. }
  117. // 限制上下拖拽边界
  118. if (state.yPum < state.boundary.top) {
  119. state.yPum = state.boundary.top;
  120. } else if (
  121. state.yPum >
  122. state.screenHeight - state.elHeight - state.boundary.bottom
  123. ) {
  124. state.yPum =
  125. state.screenHeight - state.elHeight - state.boundary.bottom;
  126. }
  127. if (props.direction != 'y') {
  128. console.log('121');
  129. target.style.left = state.xPum + 'px';
  130. }
  131. if (props.direction != 'x') {
  132. console.log('121121');
  133. target.style.top = state.yPum + 'px';
  134. }
  135. }
  136. }
  137. function touchEnd(e: any) {
  138. const target = e.currentTarget;
  139. const touch = e.changedTouches[0];
  140. let currX = touch.clientX;
  141. const rightLocation =
  142. state.screenWidth - state.elWidth - state.boundary.right;
  143. if (currX > rightLocation) {
  144. currX = rightLocation;
  145. // console.log('往右划出边界');
  146. } else if (currX < state.boundary.left) {
  147. currX = state.boundary.left;
  148. // console.log('往左划出边界');
  149. } else {
  150. currX =
  151. currX < state.screenWidth / 2 ? state.boundary.left : rightLocation;
  152. // console.log('在边界内滑动');
  153. }
  154. if (state.direction != 'y' && props.attract) {
  155. if (currX < state.screenWidth / 2) {
  156. goLeft(target);
  157. } else {
  158. goRight(target, rightLocation);
  159. }
  160. }
  161. if (state.direction != 'x') {
  162. target.style.top = state.yPum + 'px';
  163. }
  164. }
  165. function touchstart(e: any) {
  166. const target = e.currentTarget;
  167. state.startTop = target.offsetTop; // 元素距离顶部的距离
  168. state.startLeft = target.offsetLeft; // 元素距离左侧的距离
  169. state.position.x = e.touches[0].clientX; // 鼠标点击的x轴的距离
  170. state.position.y = e.touches[0].clientY; // 鼠标点击的y轴的距离
  171. myDrag.value.addEventListener('touchmove', touchMove, false);
  172. myDrag.value.addEventListener('touchend', touchEnd, false);
  173. }
  174. onMounted(() => {
  175. getInfo();
  176. state.boundary = props.boundary;
  177. });
  178. return {
  179. state,
  180. touchstart,
  181. myDrag,
  182. touchMove,
  183. touchEnd,
  184. getInfo,
  185. goLeft,
  186. goRight
  187. };
  188. }
  189. });
  190. </script>
  191. <style lang="scss">
  192. @import 'index.scss';
  193. </style>