liu-drag-button.vue 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. <template>
  2. <view>
  3. <movable-area class="movable-area" :scale-area="false">
  4. <movable-view class="movable-view" :class="!isRemove?'animation-info':''" style="pointer-events: auto;"
  5. @click="clickBtn" @touchstart="touchstart" @touchend="touchend" @change="onChange" direction="all"
  6. inertia="true" :x="x" :y="y" :disabled="disabled" :out-of-bounds="true" :damping="200" :friction="100">
  7. <slot></slot>
  8. </movable-view>
  9. </movable-area>
  10. </view>
  11. </template>
  12. <script>
  13. export default {
  14. props: {
  15. //是否禁用拖动
  16. disabled: {
  17. type: Boolean,
  18. default: false
  19. },
  20. //是否自动停靠
  21. canDocking: {
  22. type: Boolean,
  23. default: true
  24. },
  25. //按钮默认位置离底部距离(px)
  26. bottomPx: {
  27. type: Number,
  28. default: 30
  29. },
  30. //按钮默认位置离右边距离(px)
  31. rightPx: {
  32. type: Number,
  33. default: 0
  34. },
  35. },
  36. data() {
  37. return {
  38. left: 0,
  39. top: 0,
  40. isRemove: true,
  41. windowWidth: 0,
  42. windowHeight: 0,
  43. btnWidth: 0,
  44. btnHeight: 0,
  45. x: 10000,
  46. y: 10000,
  47. old: {
  48. x: 0,
  49. y: 0
  50. }
  51. };
  52. },
  53. mounted() {
  54. this.getSysInfo()
  55. },
  56. methods: {
  57. getSysInfo() {
  58. let sysInfo = uni.getSystemInfoSync()
  59. this.windowWidth = sysInfo.windowWidth
  60. this.windowHeight = sysInfo.windowHeight
  61. let view = uni.createSelectorQuery().in(this).select(".movable-view")
  62. view.boundingClientRect(rect => {
  63. this.btnWidth = rect.width
  64. this.btnHeight = rect.height
  65. this.x = this.old.x
  66. this.y = this.old.y
  67. this.$nextTick(res => {
  68. this.x = this.windowWidth - this.btnWidth - this.rightPx
  69. this.y = this.windowHeight - this.btnHeight - this.bottomPx
  70. })
  71. }).exec()
  72. },
  73. //移动按钮
  74. onChange(e) {
  75. this.old.x = e.detail.x
  76. this.old.y = e.detail.y
  77. },
  78. //开始移动
  79. touchstart(e) {
  80. this.isRemove = true
  81. },
  82. //结束移动
  83. touchend(e) {
  84. if (this.canDocking && this.old.x) {
  85. this.x = this.old.x
  86. this.y = this.old.y
  87. let bWidth = (this.windowWidth - this.btnWidth) / 2
  88. if (this.x < 0 || (this.x > 0 && this.x <= bWidth)) {
  89. this.$nextTick(res => {
  90. this.x = 0
  91. })
  92. } else {
  93. this.$nextTick(res => {
  94. this.x = this.windowWidth - this.btnWidth
  95. })
  96. }
  97. this.isRemove = false
  98. }
  99. },
  100. //点击按钮
  101. clickBtn() {
  102. this.$emit('clickBtn')
  103. }
  104. }
  105. };
  106. </script>
  107. <style scoped>
  108. .movable-view {
  109. width: 100rpx;
  110. height: 100rpx;
  111. background: linear-gradient(360deg, #287BF8 0%, #6EA8FF 100%);
  112. box-shadow: 0px 4rpx 12rpx 0px #ADC3F8;
  113. border-radius: 50rpx;
  114. color: #FFFFFF;
  115. font-size: 26rpx;
  116. touch-action: none;
  117. display: flex;
  118. align-items: center;
  119. justify-content: center;
  120. }
  121. .animation-info {
  122. transition: left .25s ease;
  123. }
  124. .movable-area {
  125. width: 100%;
  126. height: 100%;
  127. position: fixed;
  128. top: 0;
  129. left: 0;
  130. right: 0;
  131. bottom: 0;
  132. z-index: 999999 !important;
  133. pointer-events: none;
  134. }
  135. </style>