fs-fab.vue 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. <template>
  2. <view class="fs-fab">
  3. <view class="fs-fab-btn" :style="{right, bottom}">
  4. <view class="fs-fab-option" :class="{'fs-fab-scale': visible}">
  5. <slot name="option">
  6. <fs-avatar
  7. class="fs-fab-option-gutter"
  8. v-for="(item,index) in options"
  9. :key="index"
  10. :size="size"
  11. :bgColor="item.bgColor"
  12. :bgColorType="item.bgColorType"
  13. @click="handleOption(item)">
  14. {{item.name}}
  15. </fs-avatar>
  16. </slot>
  17. </view>
  18. <fs-avatar :size="size" bgColorType="danger" @click="handleToggle" v-if="visible">
  19. <fs-icon type="icon-close" :size="iconSize"></fs-icon>
  20. </fs-avatar>
  21. <fs-avatar :size="size" :bgColor="bgColor" @click="handleToggle" v-else>
  22. <slot name="icon">
  23. <fs-icon type="icon-plus" :size="iconSize" class="fs-fab-plus" :class="{'fs-fab-visible':visible}"></fs-icon>
  24. </slot>
  25. </fs-avatar>
  26. </view>
  27. <fs-mask v-if="showMask" v-model="visible"></fs-mask>
  28. </view>
  29. </template>
  30. <script setup>
  31. import { ref } from 'vue'
  32. const props = defineProps({
  33. right: {
  34. type: String,
  35. default: '40rpx'
  36. },
  37. bottom: {
  38. type: String,
  39. default: '40rpx'
  40. },
  41. options: {
  42. type: Array,
  43. default: () => []
  44. },
  45. size: {
  46. type: String,
  47. default: '120rpx'
  48. },
  49. iconSize: {
  50. type: String,
  51. default: '50rpx'
  52. },
  53. bgColor: String,
  54. showMask: Boolean
  55. })
  56. const emits = defineEmits(['clickOption'])
  57. const visible = ref(false)
  58. const handleToggle = () => {
  59. visible.value = !visible.value
  60. }
  61. const handleOption = item => {
  62. close()
  63. emits('clickOption',item)
  64. }
  65. const close = () => {
  66. visible.value = false
  67. }
  68. defineExpose({
  69. close
  70. })
  71. </script>
  72. <style lang="scss" scoped>
  73. .fs-fab{
  74. &-btn{
  75. position: fixed;
  76. margin-bottom: var(--window-bottom);
  77. z-index: 900;
  78. }
  79. &-plus{
  80. transition: all .2s;
  81. }
  82. &-visible{
  83. transform: rotate(315deg);
  84. }
  85. &-option{
  86. display: flex;
  87. flex-direction: column;
  88. margin-bottom: 30rpx;
  89. transition: all .2s;
  90. transform: translateY(-50%);
  91. opacity: 0;
  92. z-index: -1;
  93. &-gutter{
  94. margin-top: 20rpx;
  95. }
  96. }
  97. &-scale{
  98. transform: translateY(0);
  99. opacity: 1;
  100. z-index: 900;
  101. }
  102. }
  103. </style>