tui-fab.vue 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255
  1. <template>
  2. <view @touchmove.stop.prevent>
  3. <view class="tui-fab-box" :class="{'tui-fab-right':!left || (left && right)}" :style="{left:getLeft(),right:getRight(),bottom:bottom+'rpx'}">
  4. <view class="tui-fab-btn" :class="{'tui-visible':isOpen,'tui-fab-hidden':hidden}">
  5. <view class="tui-fab-item-box" :class="{'tui-fab-item-left':left && !right && item.imgUrl}" v-for="(item,index) in btnList"
  6. :key="index" @tap.stop="handleClick(index)">
  7. <view :class="[left && !right?'tui-text-left':'tui-text-right']" v-if="item.imgUrl" :style="{fontSize:item.fontSize+'rpx',color:item.color}">{{item.text || ""}}</view>
  8. <view class="tui-fab-item" :style="{width:width+'rpx',height:height+'rpx',background:item.bgColor || bgColor,borderRadius:radius}">
  9. <view class="tui-fab-title" v-if="!item.imgUrl" :style="{fontSize:item.fontSize+'rpx',color:item.color}">{{item.text || ""}}</view>
  10. <image :src="item.imgUrl" class="tui-fab-img" v-else :style="{width:item.imgWidth+'rpx',height:item.imgHeight+'rpx'}"></image>
  11. </view>
  12. </view>
  13. </view>
  14. <view class="tui-fab-item" :class="{'tui-active':isOpen}" :style="{width:width+'rpx',height:height+'rpx',borderRadius:radius,background:bgColor,color:color}"
  15. @tap.stop="handleClick(-1)">
  16. <view class="tui-fab-icon tui-icon-plus"></view>
  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. //rpx 为0时值为auto
  28. left: {
  29. type: Number,
  30. default: 0
  31. },
  32. //rpx 当为0时且left不为0,值为auto
  33. right: {
  34. type: Number,
  35. default: 80
  36. },
  37. //rpx bottom值
  38. bottom: {
  39. type: Number,
  40. default: 100
  41. },
  42. //默认按钮 宽度 rpx
  43. width: {
  44. type: Number,
  45. default: 108
  46. },
  47. //默认按钮 高度 rpx
  48. height: {
  49. type: Number,
  50. default: 108
  51. },
  52. //圆角值
  53. radius: {
  54. type: String,
  55. default: "50%"
  56. },
  57. //默认按钮背景颜色
  58. bgColor: {
  59. type: String,
  60. default: "#C74547"
  61. },
  62. //字体颜色
  63. color: {
  64. type: String,
  65. default: "#fff"
  66. },
  67. //拓展按钮
  68. // bgColor: "#C74547",
  69. // //图标/图片地址
  70. // imgUrl: "/static/images/fab/fab_reward.png",
  71. // //图片高度 rpx
  72. // imgHeight: 60,
  73. // //图片宽度 rpx
  74. // imgWidth: 60,
  75. // //名称
  76. // text: "名称",
  77. // //字体大小
  78. // fontSize: 30,
  79. // //字体颜色
  80. // color: "#fff"
  81. btnList: {
  82. type: Array,
  83. default () {
  84. return []
  85. }
  86. },
  87. //点击遮罩 是否可关闭
  88. maskClosable: {
  89. type: Boolean,
  90. default: false
  91. }
  92. },
  93. data() {
  94. return {
  95. isOpen: false,
  96. hidden: true,
  97. timer: null
  98. };
  99. },
  100. methods: {
  101. getLeft() {
  102. let val = "auto"
  103. if (this.left && !this.right) {
  104. val = this.left + 'rpx'
  105. }
  106. return val
  107. },
  108. getRight() {
  109. let val = this.right + 'rpx'
  110. if (this.left && !this.right) {
  111. val = "auto"
  112. }
  113. return val
  114. },
  115. handleClick: function(index) {
  116. this.hidden = false
  117. clearTimeout(this.timer)
  118. if (index == -1 && this.btnList.length) {
  119. this.isOpen = !this.isOpen
  120. } else {
  121. this.$emit("click", {
  122. index: index
  123. })
  124. this.isOpen = false
  125. }
  126. if (!this.isOpen) {
  127. this.timer = setTimeout(() => {
  128. this.hidden = true
  129. }, 200)
  130. }
  131. },
  132. handleClickCancel: function() {
  133. if (!this.maskClosable) return;
  134. this.isOpen = false
  135. }
  136. },
  137. beforeDestroy() {
  138. clearTimeout(this.timer)
  139. this.timer = null
  140. }
  141. }
  142. </script>
  143. <style>
  144. @font-face {
  145. font-family: 'tuifab';
  146. src: url(data:application/font-woff;charset=utf-8;base64,d09GRgABAAAAAAREAA0AAAAABnAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABGRlRNAAAEKAAAABoAAAAciPExJUdERUYAAAQIAAAAHgAAAB4AKQAKT1MvMgAAAaAAAABCAAAAVjyBSAVjbWFwAAAB9AAAAD4AAAFCAA/pvmdhc3AAAAQAAAAACAAAAAj//wADZ2x5ZgAAAkAAAABRAAAAYFkYQQNoZWFkAAABMAAAADAAAAA2Fm5OF2hoZWEAAAFgAAAAHQAAACQH3QOFaG10eAAAAeQAAAAPAAAAEAwAAANsb2NhAAACNAAAAAoAAAAKADAAAG1heHAAAAGAAAAAHwAAACABDwAobmFtZQAAApQAAAFJAAACiCnmEVVwb3N0AAAD4AAAAB8AAAAx2XRuznjaY2BkYGAAYtGolt54fpuvDNwsDCBwc1krH5xm/t/I/J+5FsjlYGACiQIAGAEKZHjaY2BkYGBu+N/AEMPCAALM/xkYGVABCwBZ4wNrAAAAeNpjYGRgYGBhkGEA0QwMTEDMBYQMDP/BfAYAC4kBOAB42mNgZGFgnMDAysDA1Ml0hoGBoR9CM75mMGLkAIoysDIzYAUBaa4pDA7PhJ8JMzf8b2CIYW5gaAAKM4LkAN21DAEAAHjaY2GAABYIZgYAAIMAEAB42mNgYGBmgGAZBkYGELAB8hjBfBYGBSDNAoRA/jPh//8hpOQHqEoGRjYGGJOBkQlIMDGgAkaGYQ8AUSIHswAAAAAAAAAAAAAAMAAAeNpjYGRg/t/I/J+5lkGagYFRUVCPUYmNXVCRj1FETFxRUI7RyMxcUNGO0USN+fS/HEY5XTnGfznicnLijFPAHMYpYnJyjFvBlBgWBQBNJxKpAAAAeNp9kD1OAzEQhZ/zByQSQiCoXVEA2vyUKRMp9Ailo0g23pBo1155nUg5AS0VB6DlGByAGyDRcgpelkmTImvt6PObmeexAZzjGwr/3yXuhBWO8ShcwREy4Sr1F+Ea+V24jhY+hRvUf4SbuFUD4RYu1BsdVO2Eu5vSbcsKZxgIV3CKJ+Eq9ZVwjfwqXMcVPoQb1L+EmxjjV7iFa2WpDOFhMEFgnEFjig3jAjEcLJIyBtahOfRmEsxMTzd6ETubOBso71dilwMeaDnngCntPbdmvkon/mDLgdSYbh4FS7YpjS4idCgbXyyc1d2oc7D9nu22tNi/a4E1x+xRDWzU/D3bM9JIbAyvkJI18jK3pBJTj2hrrPG7ZynW814IiU68y/SIx5o0dTr3bmniwOLn8owcfbS5kj33qBw+Y1kIeb/dTsQgil2GP5PYcRkAAAB42mNgYoAALjDJyIAOWMCiTIxMbFmZiRmJ+QALXAKKAAAAAAH//wACAAEAAAAMAAAAFgAAAAIAAQADAAMAAQAEAAAAAgAAAAB42mNgYGBkAIKrS9Q5QPTNZa18MBoAPbcFzgAA) format('woff');
  147. font-weight: normal;
  148. font-style: normal;
  149. }
  150. .tui-fab-icon {
  151. font-family: "tuifab" !important;
  152. font-style: normal;
  153. -webkit-font-smoothing: antialiased;
  154. -moz-osx-font-smoothing: grayscale;
  155. padding: 10rpx;
  156. }
  157. .tui-icon-plus:before {
  158. content: "\e613";
  159. }
  160. .tui-fab-box {
  161. display: flex;
  162. justify-content: center;
  163. flex-direction: column;
  164. position: fixed;
  165. z-index: 99997;
  166. }
  167. .tui-fab-right {
  168. align-items: flex-end;
  169. }
  170. .tui-fab-btn {
  171. transform: scale(0);
  172. transition: all 0.2s ease-in-out;
  173. opacity: 0;
  174. visibility: hidden;
  175. }
  176. .tui-fab-hidden {
  177. height: 0;
  178. width: 0;
  179. }
  180. .tui-fab-item-box {
  181. display: flex;
  182. align-items: center;
  183. justify-content: flex-end;
  184. padding-bottom: 40rpx;
  185. }
  186. .tui-fab-item-left {
  187. flex-flow: row-reverse;
  188. }
  189. .tui-fab-title {
  190. width: 90%;
  191. text-align: center;
  192. white-space: nowrap;
  193. overflow: hidden;
  194. text-overflow: ellipsis;
  195. }
  196. .tui-text-left {
  197. padding-left: 28rpx;
  198. }
  199. .tui-text-right {
  200. padding-right: 28rpx;
  201. }
  202. .tui-fab-img {
  203. display: block;
  204. }
  205. .tui-fab-item {
  206. display: flex;
  207. align-items: center;
  208. justify-content: center;
  209. box-shadow: 0 0 5px 2px rgba(0, 0, 0, 0.1);
  210. transition: all 0.2s linear;
  211. }
  212. .tui-radius {
  213. border-radius: 50%;
  214. }
  215. .tui-active {
  216. transform: rotate(135deg);
  217. }
  218. .tui-fab-mask {
  219. position: fixed;
  220. top: 0;
  221. left: 0;
  222. right: 0;
  223. bottom: 0;
  224. background: rgba(0, 0, 0, 0.75);
  225. z-index: 99996;
  226. transition: all 0.2s ease-in-out;
  227. opacity: 0;
  228. visibility: hidden;
  229. }
  230. .tui-visible {
  231. visibility: visible;
  232. opacity: 1;
  233. transform: scale(1);
  234. }
  235. </style>