fab.vue 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272
  1. <template>
  2. <!-- 全局公共悬浮按钮 -->
  3. <view @touchmove.stop.prevent>
  4. <view class="tui-fab-box" :class="{'tui-fab-right':!left || (left && right)}" :style="{left:getLeft(),right:getRight(),bottom:bottom+'rpx'}" @touchstart="down" @touchmove="move" @touchend="end" id="moveDiv">
  5. <view class="tui-fab-btn" :class="{'tui-visible':isOpen,'tui-fab-hidden':hidden}">
  6. <div class="tui-fab-item-box" v-for="(item,index) in btnList" :key="index" @tap.stop="handleClick(index)">
  7. <div class="item-list">
  8. <div class="list-icon">
  9. <i class="iconfont" :class="[item.icon]"></i>
  10. </div>
  11. <div class="list-name">{{ item.name }}</div>
  12. </div>
  13. </div>
  14. </view>
  15. <view class="tui-fab-item" :class="{'tui-active':isOpen}" @tap.stop="handleClick(-1)">
  16. <i class="iconfont" :class="[isOpen? 'icontupiantianjia' : 'iconcaidan']"></i>
  17. </view>
  18. </view>
  19. <view class="tui-fab-mask" :class="{'tui-visible':isOpen}" @tap="handleClickCancel"></view>
  20. </view>
  21. </template>
  22. <script>
  23. // 拓展出来的按钮不应多于6个,否则违反了作为悬浮按钮的快速、高效的原则
  24. export default {
  25. name: 'tuiFab',
  26. props: {
  27. // 点击遮罩 是否可关闭
  28. maskClosable: {
  29. type: Boolean,
  30. default: true
  31. }
  32. },
  33. data() {
  34. return {
  35. isOpen: false,
  36. hidden: true,
  37. timer: null,
  38. btnList: [
  39. {
  40. name: '首页',
  41. icon: 'iconshouye',
  42. url: '/admin/home/workbench'
  43. },
  44. {
  45. name: '添加图库',
  46. icon: 'icontianjiatuku',
  47. url: '/admin/home/workbench'
  48. },
  49. {
  50. name: '发货',
  51. icon: 'iconfahuo',
  52. url: '/admin/home/workbench'
  53. }
  54. ],
  55. winWidth: 750,
  56. winHeight: 1336,
  57. left: 0,
  58. right: 20,
  59. bottom: 140,
  60. position: { x: 0, y: 0 },
  61. nx: '',
  62. ny: '',
  63. dx: '',
  64. dy: '',
  65. xPum: '',
  66. yPum: '',
  67. flags: false
  68. }
  69. },
  70. mounted() {
  71. uni.getSystemInfo({
  72. success: res => {
  73. this.winWidth = res.screenWidth * 2
  74. this.winHeight = res.windowHeight * 2
  75. }
  76. })
  77. },
  78. methods: {
  79. getLeft() {
  80. let val = 'auto'
  81. if (this.left && !this.right) {
  82. val = this.left + 'rpx'
  83. }
  84. return val
  85. },
  86. getRight() {
  87. let val = this.right + 'rpx'
  88. if (this.left && !this.right) {
  89. val = 'auto'
  90. }
  91. return val
  92. },
  93. handleClick: function(index) {
  94. this.hidden = false
  95. clearTimeout(this.timer)
  96. if (index == -1 && this.btnList.length) {
  97. this.isOpen = !this.isOpen
  98. } else {
  99. this.$emit('click', {
  100. index: index
  101. })
  102. this.isOpen = false
  103. }
  104. if (!this.isOpen) {
  105. this.timer = setTimeout(() => {
  106. this.hidden = true
  107. }, 200)
  108. }
  109. },
  110. handleClickCancel: function() {
  111. if (!this.maskClosable) return
  112. this.isOpen = false
  113. },
  114. // 实现移动端拖拽
  115. down() {
  116. this.flags = true
  117. var touch
  118. if (event.touches) {
  119. touch = event.touches[0]
  120. } else {
  121. touch = event
  122. }
  123. this.position.x = touch.clientX
  124. this.position.y = touch.clientY
  125. this.dx = moveDiv.offsetLeft
  126. this.dy = moveDiv.offsetTop
  127. // console.log('down', touch)
  128. },
  129. move() {
  130. event.preventDefault()
  131. if (this.flags) {
  132. let touch, totalHeight
  133. let wheight = this.winWidth
  134. let objHeight = 50
  135. if (event.touches) {
  136. touch = event.touches[0]
  137. } else {
  138. touch = event
  139. }
  140. this.nx = touch.clientX - this.position.x // 拖动x长度
  141. this.ny = touch.clientY - this.position.y // 拖动y长度
  142. this.xPum = this.dx + this.nx // 距离左侧距离
  143. this.yPum = this.dy + this.ny // 距离顶部距离
  144. // console.log('lalaal', wheight, this.nx, this.ny, this.xPum, this.yPum)
  145. if (this.navType) {
  146. if (this.yPum > 0) {
  147. if (wheight - objHeight - this.yPum > 0) {
  148. totalHeight = wheight - objHeight - this.yPum
  149. } else {
  150. totalHeight = 0
  151. }
  152. }
  153. } else {
  154. objHeight += 200
  155. if (this.yPum - objHeight > 0) {
  156. if (wheight - this.yPum > 0) {
  157. totalHeight = wheight - this.yPum
  158. } else {
  159. totalHeight = 0
  160. }
  161. }
  162. }
  163. // console.log('totalHeight', totalHeight)
  164. this.bottom = totalHeight
  165. // console.log('this.bottom', this.bottom)
  166. }
  167. },
  168. end() {
  169. this.flags = false
  170. }
  171. },
  172. beforeDestroy() {
  173. clearTimeout(this.timer)
  174. this.timer = null
  175. }
  176. }
  177. </script>
  178. <style lang="scss" scoped>
  179. .tui-fab-box {
  180. width: 100upx;
  181. display: flex;
  182. justify-content: center;
  183. flex-direction: column;
  184. position: fixed;
  185. z-index: 99997;
  186. }
  187. .tui-fab-right {
  188. align-items: center;
  189. }
  190. .tui-fab-btn {
  191. transform: scale(0);
  192. transition: all 0.2s ease-in-out;
  193. opacity: 0;
  194. visibility: hidden;
  195. background-color: #fff;
  196. border-top-left-radius: 80upx;
  197. border-top-right-radius: 80upx;
  198. position: relative;
  199. top: 40upx;
  200. padding: 30upx 0 30upx;
  201. }
  202. .tui-fab-hidden {
  203. height: 0;
  204. width: 0;
  205. }
  206. .tui-fab-item-box {
  207. display: flex;
  208. align-items: center;
  209. justify-content: center;
  210. padding-bottom: 30upx;
  211. .item-list {
  212. text-align: center;
  213. color: #333;
  214. }
  215. .list-name {
  216. font-weight: 400;
  217. transform: scale(0.8);
  218. }
  219. }
  220. .tui-fab-item {
  221. display: flex;
  222. align-items: center;
  223. justify-content: center;
  224. box-shadow: 0 0 5upx 2upx rgba(0, 0, 0, 0.1);
  225. transition: all 0.2s linear;
  226. background-image: linear-gradient(0deg, #357eff, #0dc9fd);
  227. width: 100%;
  228. height: 100upx;
  229. border-radius: 50%;
  230. color: #fff;
  231. }
  232. .tui-active {
  233. transform: rotate(135deg);
  234. }
  235. .tui-fab-mask {
  236. position: fixed;
  237. top: 0;
  238. left: 0;
  239. right: 0;
  240. bottom: 0;
  241. background: rgba(0, 0, 0, 0.75);
  242. z-index: 99996;
  243. transition: all 0.2s ease-in-out;
  244. opacity: 0;
  245. visibility: hidden;
  246. }
  247. .tui-visible {
  248. visibility: visible;
  249. opacity: 1;
  250. transform: scale(1);
  251. }
  252. </style>