tui-fab.vue 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  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. <text class="tui-fab-icon tui-icon-plus" v-if="!custom"></text>
  17. <slot></slot>
  18. </view>
  19. </view>
  20. <view class="tui-fab-mask" :class="{'tui-visible':isOpen}" @tap="handleClickCancel"></view>
  21. </view>
  22. </template>
  23. <script>
  24. //拓展出来的按钮不应多于6个,否则违反了作为悬浮按钮的快速、高效的原则
  25. export default {
  26. name: "tuiFab",
  27. props: {
  28. //rpx 为0时值为auto
  29. left: {
  30. type: Number,
  31. default: 0
  32. },
  33. //rpx 当为0时且left不为0,值为auto
  34. right: {
  35. type: Number,
  36. default: 80
  37. },
  38. //rpx bottom值
  39. bottom: {
  40. type: Number,
  41. default: 100
  42. },
  43. //默认按钮 宽度 rpx
  44. width: {
  45. type: Number,
  46. default: 108
  47. },
  48. //默认按钮 高度 rpx
  49. height: {
  50. type: Number,
  51. default: 108
  52. },
  53. //圆角值
  54. radius: {
  55. type: String,
  56. default: "50%"
  57. },
  58. //默认按钮自定义内容[替换加号]
  59. custom:{
  60. type:Boolean,
  61. default:false
  62. },
  63. //默认按钮背景颜色
  64. bgColor: {
  65. type: String,
  66. default: "#5677fc"
  67. },
  68. //字体颜色
  69. color: {
  70. type: String,
  71. default: "#fff"
  72. },
  73. //拓展按钮
  74. // bgColor: "#5677fc",
  75. // //图标/图片地址
  76. // imgUrl: "/static/images/fab/fab_reward.png",
  77. // //图片高度 rpx
  78. // imgHeight: 60,
  79. // //图片宽度 rpx
  80. // imgWidth: 60,
  81. // //名称
  82. // text: "名称",
  83. // //字体大小
  84. // fontSize: 30,
  85. // //字体颜色
  86. // color: "#fff"
  87. btnList: {
  88. type: Array,
  89. default () {
  90. return []
  91. }
  92. },
  93. //点击遮罩 是否可关闭
  94. maskClosable: {
  95. type: Boolean,
  96. default: false
  97. }
  98. },
  99. data() {
  100. return {
  101. isOpen: false,
  102. hidden: true,
  103. timer: null
  104. };
  105. },
  106. methods: {
  107. getLeft() {
  108. let val = "auto"
  109. if (this.left && !this.right) {
  110. val = this.left + 'rpx'
  111. }
  112. return val
  113. },
  114. getRight() {
  115. let val = this.right + 'rpx'
  116. if (this.left && !this.right) {
  117. val = "auto"
  118. }
  119. return val
  120. },
  121. handleClick: function(index) {
  122. this.hidden = false
  123. clearTimeout(this.timer)
  124. if (index == -1 && this.btnList.length) {
  125. this.isOpen = !this.isOpen
  126. } else {
  127. this.$emit("click", {
  128. index: index
  129. })
  130. this.isOpen = false
  131. }
  132. if (!this.isOpen) {
  133. this.timer = setTimeout(() => {
  134. this.hidden = true
  135. }, 200)
  136. }
  137. },
  138. handleClickCancel: function() {
  139. if (!this.maskClosable) return;
  140. this.isOpen = false
  141. }
  142. },
  143. beforeDestroy() {
  144. clearTimeout(this.timer)
  145. this.timer = null
  146. }
  147. }
  148. </script>
  149. <style scoped>
  150. @font-face {
  151. font-family: 'tuifab';
  152. 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');
  153. font-weight: normal;
  154. font-style: normal;
  155. }
  156. .tui-fab-icon {
  157. font-family: "tuifab" !important;
  158. font-style: normal;
  159. -webkit-font-smoothing: antialiased;
  160. -moz-osx-font-smoothing: grayscale;
  161. padding: 10rpx;
  162. }
  163. .tui-icon-plus:before {
  164. content: "\e613";
  165. }
  166. .tui-fab-box {
  167. display: flex;
  168. justify-content: center;
  169. flex-direction: column;
  170. position: fixed;
  171. z-index: 99997;
  172. }
  173. .tui-fab-right {
  174. align-items: flex-end;
  175. }
  176. .tui-fab-btn {
  177. transform: scale(0);
  178. transition: all 0.2s ease-in-out;
  179. opacity: 0;
  180. visibility: hidden;
  181. }
  182. .tui-fab-hidden {
  183. height: 0;
  184. width: 0;
  185. }
  186. .tui-fab-item-box {
  187. display: flex;
  188. align-items: center;
  189. justify-content: flex-end;
  190. padding-bottom: 40rpx;
  191. }
  192. .tui-fab-item-left {
  193. flex-flow: row-reverse;
  194. }
  195. .tui-fab-title {
  196. width: 90%;
  197. text-align: center;
  198. white-space: nowrap;
  199. overflow: hidden;
  200. text-overflow: ellipsis;
  201. }
  202. .tui-text-left {
  203. padding-left: 28rpx;
  204. }
  205. .tui-text-right {
  206. padding-right: 28rpx;
  207. }
  208. .tui-fab-img {
  209. display: block;
  210. }
  211. .tui-fab-item {
  212. display: flex;
  213. align-items: center;
  214. justify-content: center;
  215. box-shadow: 0 0 5px 2px rgba(0, 0, 0, 0.1);
  216. transition: all 0.2s linear;
  217. }
  218. .tui-radius {
  219. border-radius: 50%;
  220. }
  221. .tui-active {
  222. transform: rotate(135deg);
  223. }
  224. .tui-fab-mask {
  225. position: fixed;
  226. top: 0;
  227. left: 0;
  228. right: 0;
  229. bottom: 0;
  230. background: rgba(0, 0, 0, 0.75);
  231. z-index: 99996;
  232. transition: all 0.2s ease-in-out;
  233. opacity: 0;
  234. visibility: hidden;
  235. }
  236. .tui-visible {
  237. visibility: visible;
  238. opacity: 1;
  239. transform: scale(1);
  240. }
  241. </style>