index.vue 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. <template>
  2. <view
  3. id="drag-button"
  4. class="drag-container"
  5. :class="{transition: autoDocking && !moving }"
  6. :style="{
  7. left: `${left}px`,
  8. top: `${top}px`,
  9. width: `${size}rpx`,
  10. height: `${size}rpx`,
  11. zIndex: zIndex
  12. }"
  13. @touchend="touchend"
  14. @touchmove.stop.prevent="touchmove"
  15. >
  16. <slot />
  17. </view>
  18. </template>
  19. <script>
  20. export default {
  21. name: 'DragButton',
  22. props: {
  23. /**
  24. * 按钮大小
  25. */
  26. size: {
  27. type: Number,
  28. default: 200
  29. },
  30. /**
  31. * 层级
  32. */
  33. zIndex: {
  34. type: Number,
  35. default: 999
  36. },
  37. /**
  38. * x轴边界限制
  39. */
  40. xEdge: {
  41. type: Number,
  42. default: 0
  43. },
  44. /**
  45. * y轴边界限制
  46. */
  47. yEdge: {
  48. type: Number,
  49. default: 0
  50. },
  51. /**
  52. * 自动停靠
  53. */
  54. autoDocking: {
  55. type: Boolean,
  56. default: true
  57. },
  58. // 是否开启沿袭拖动位置
  59. isAutoPosition: {
  60. type: Boolean,
  61. default: true
  62. },
  63. // 超出左右边界长度
  64. exceedBorderLength: {
  65. type: Number,
  66. default: 0
  67. }
  68. },
  69. data() {
  70. return {
  71. top: 500,
  72. left: 300,
  73. width: 0,
  74. height: 0,
  75. moving: true,
  76. }
  77. },
  78. mounted() {
  79. this.init()
  80. },
  81. methods: {
  82. init() {
  83. // 获取窗口尺寸
  84. const { windowWidth, windowHeight, windowTop } = uni.getSystemInfoSync()
  85. this._windowWidth = windowWidth
  86. this._windowHeight = windowHeight
  87. if (windowTop) {
  88. this._windowHeight += windowTop
  89. }
  90. // 计算按钮初始位置
  91. const query = uni.createSelectorQuery().in(this)
  92. query.select('#drag-button').boundingClientRect(data => {
  93. if (!data) return
  94. console.log(data);
  95. const { width, height } = data
  96. this.width = width
  97. this.height = height
  98. this._offsetWidth = width / 2
  99. this._offsetHeight = height / 2
  100. let positionStorage = uni.getStorageSync('dragBtn');
  101. if (this.isAutoPosition && positionStorage){
  102. this.left = positionStorage.left;
  103. this.top = positionStorage.top;
  104. }else {
  105. this.left = (this._windowWidth - this.width - this.xEdge) > 0 ? this._windowWidth - this.width - this.xEdge + this.exceedBorderLength : 0 - this.exceedBorderLength
  106. this.top = (this._windowHeight - this.height - this.yEdge) > 0 ? this._windowHeight - this.height - this.yEdge : 0
  107. if (this.isAutoPosition){
  108. uni.setStorageSync('dragBtn', {
  109. top: this.top,
  110. left: this.left
  111. });
  112. }
  113. }
  114. }).exec()
  115. },
  116. // 拖动
  117. touchmove({ touches }) {
  118. if (touches.length !== 1) return false
  119. this.moving = true
  120. const { clientX, clientY } = touches[0]
  121. this.left = clientX - this._offsetWidth
  122. let _clientY = clientY - this._offsetHeight
  123. // #ifdef H5
  124. _clientY += this.height
  125. // #endif
  126. this.top = _clientY
  127. },
  128. // 松手
  129. touchend() {
  130. // 左右边界,松手自动停靠
  131. if (this.autoDocking) {
  132. const rigthEdge = this._windowWidth - this.width - this.xEdge
  133. if (this.left < this._windowWidth / 2 - this._offsetWidth) {
  134. this.left = this.xEdge - this.exceedBorderLength
  135. } else {
  136. this.left = rigthEdge + this.exceedBorderLength
  137. }
  138. }
  139. // 上下边界
  140. const bottomEdge = this._windowHeight - this.height - this.yEdge
  141. if (this.top < this.yEdge) {
  142. this.top = this.yEdge
  143. } else if (this.top > bottomEdge) {
  144. this.top = bottomEdge
  145. }
  146. // 记录位置变化
  147. if (this.isAutoPosition){
  148. uni.setStorageSync('dragBtn', {
  149. top: this.top,
  150. left: this.left
  151. });
  152. }
  153. console.log(uni.getStorageSync('dragBtn'))
  154. this.moving = false
  155. },
  156. }
  157. }
  158. </script>
  159. <style lang="scss" scoped>
  160. .drag-container {
  161. display: flex;
  162. justify-content: center;
  163. align-items: center;
  164. border-radius: 50%;
  165. position: fixed;
  166. &.transition {
  167. transition: all .3s ease;
  168. }
  169. }
  170. </style>