fab-tool.vue 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. <template>
  2. <view class="fab-tool">
  3. <view id="toolfab">
  4. <slot></slot>
  5. </view>
  6. <view class="fab-tool-content" :style="placementStyle" id="placementfab">
  7. <slot name="content" v-if="visible"></slot>
  8. </view>
  9. </view>
  10. </template>
  11. <script>
  12. export default {
  13. props: {
  14. visible: {
  15. type: Boolean,
  16. default: false
  17. },
  18. placement: {
  19. type: String,
  20. default: 'auto' // 'auto' | 'top-start' | 'top-center' | 'top-end' | 'bottom-start' | 'bottom-center' | 'bottom-end'
  21. }
  22. },
  23. data() {
  24. return {
  25. placementHeight: '0',
  26. placementType: ''
  27. }
  28. },
  29. watch: {
  30. visible(newVal) {
  31. if (newVal) {
  32. const { screenWidth } = uni.getSystemInfoSync()
  33. this.$nextTick(() => {
  34. let placementWidth = 0
  35. uni
  36. .createSelectorQuery()
  37. .in(this)
  38. .select('#placementfab')
  39. .boundingClientRect((res) => {
  40. this.placementHeight = -res.height + 'px'
  41. placementWidth = res.width
  42. })
  43. .exec()
  44. // 开启自动模式后
  45. if (this.placement == 'auto') {
  46. uni
  47. .createSelectorQuery()
  48. .in(this)
  49. .select('#toolfab')
  50. .boundingClientRect((res) => {
  51. let leftRemain = res.left
  52. let rightRemain = screenWidth - leftRemain
  53. if (rightRemain > placementWidth) {
  54. this.placementType = 'bottom-start'
  55. } else if (leftRemain > placementWidth) {
  56. this.placementType = 'bottom-end'
  57. } else {
  58. this.placementType = 'bottom-center'
  59. }
  60. })
  61. .exec()
  62. }
  63. })
  64. }
  65. }
  66. },
  67. mounted() {
  68. this.placementType = this.placement
  69. },
  70. computed: {
  71. placementStyle() {
  72. let position = {}
  73. switch (this.placementType) {
  74. case 'top-start':
  75. position = {
  76. top: this.placementHeight,
  77. left: 0
  78. }
  79. break
  80. case 'top-center':
  81. position = {
  82. top: this.placementHeight,
  83. left: '50%',
  84. transform: 'translateX(-50%)'
  85. }
  86. break
  87. case 'top-end':
  88. position = {
  89. top: this.placementHeight,
  90. right: 0
  91. }
  92. break
  93. case 'bottom-start':
  94. position = {
  95. bottom: this.placementHeight,
  96. left: 0
  97. }
  98. break
  99. case 'bottom-center':
  100. position = {
  101. bottom: this.placementHeight,
  102. left: '50%',
  103. transform: 'translateX(-50%)'
  104. }
  105. break
  106. case 'bottom-end':
  107. position = {
  108. bottom: this.placementHeight,
  109. right: 0
  110. }
  111. break
  112. default:
  113. break
  114. }
  115. return position
  116. }
  117. },
  118. methods: {
  119. //
  120. }
  121. }
  122. </script>
  123. <style lang="scss">
  124. .fab-tool {
  125. position: relative;
  126. .fab-tool-content {
  127. position: absolute;
  128. z-index: 999;
  129. background-color: #ffffff;
  130. box-shadow: -2px -2px 4px rgba(0, 0, 0, 0.05), 2px 2px 4px rgba(0, 0, 0, 0.05);
  131. border-radius: 12rpx;
  132. box-sizing: border-box;
  133. }
  134. }
  135. </style>