index.vue 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. <template>
  2. <view v-if="show"
  3. :style="{width: systemInfo.width + 'px', height: systemInfo.height + 'px', backgroundColor: bgcolor, position: 'absolute', left: 0, top: 0, zIndex: 9998}">
  4. <view v-for="(item,rect_idx) in skeletonRectLists" :key="rect_idx + 'rect'"
  5. :class="[loading == 'chiaroscuro' ? 'chiaroscuro' : '']"
  6. :style="{width: item.width + 'px', height: item.height + 'px', backgroundColor: 'rgb(194, 207, 214,.3)', position: 'absolute', left: item.left + 'px', top: item.top + 'px'}">
  7. </view>
  8. <view v-for="(item,circle_idx) in skeletonCircleLists" :key="circle_idx + 'circle'"
  9. :class="loading == 'chiaroscuro' ? 'chiaroscuro' : ''"
  10. :style="{width: item.width + 'px', height: item.height + 'px', backgroundColor: 'rgb(194, 207, 214,.3)', borderRadius: item.width + 'px', position: 'absolute', left: item.left + 'px', top: item.top + 'px'}">
  11. </view>
  12. <view class="spinbox" v-if="loading == 'spin'">
  13. <view class="spin"></view>
  14. </view>
  15. </view>
  16. </template>
  17. <script>
  18. export default {
  19. name: "skeleton",
  20. props: {
  21. bgcolor: {
  22. type: String,
  23. value: '#FFF'
  24. },
  25. selector: {
  26. type: String,
  27. value: 'skeleton'
  28. },
  29. loading: {
  30. type: String,
  31. value: 'spin'
  32. },
  33. show: {
  34. type: Boolean,
  35. value: false
  36. },
  37. isNodes: {
  38. type: Number,
  39. value: false
  40. } //控制什么时候开始抓取元素节点,只要数值改变就重新抓取
  41. },
  42. data() {
  43. return {
  44. loadingAni: ['spin', 'chiaroscuro'],
  45. systemInfo: {},
  46. skeletonRectLists: [],
  47. skeletonCircleLists: []
  48. }
  49. },
  50. watch: {
  51. isNodes(val) {
  52. this.readyAction();
  53. }
  54. },
  55. mounted() {
  56. this.attachedAction();
  57. },
  58. methods: {
  59. attachedAction: function() {
  60. //默认的首屏宽高,防止内容闪现
  61. const systemInfo = uni.getSystemInfoSync();
  62. this.systemInfo = {
  63. width: systemInfo.windowWidth,
  64. height: systemInfo.windowHeight
  65. };
  66. this.loading = this.loadingAni.includes(this.loading) ? this.loading : 'spin';
  67. },
  68. readyAction: function() {
  69. const that = this;
  70. //绘制背景
  71. uni.createSelectorQuery().selectAll(`.${this.selector}`).boundingClientRect(function(res) {
  72. if (res[0].length > 0)
  73. that.systemInfo.height = res[0][0].height + res[0][0].top;
  74. }).exec()
  75. //绘制矩形
  76. this.rectHandle();
  77. //绘制圆形
  78. this.radiusHandle();
  79. },
  80. rectHandle: function() {
  81. const that = this;
  82. //绘制不带样式的节点
  83. uni.createSelectorQuery().selectAll(`.${this.selector}-rect`).boundingClientRect().exec(function(res) {
  84. that.skeletonRectLists = res[0];
  85. });
  86. },
  87. radiusHandle() {
  88. const that = this;
  89. uni.createSelectorQuery().selectAll(`.${this.selector}-radius`).boundingClientRect().exec(function(res) {
  90. console.log(res)
  91. that.skeletonCircleLists = res[0];
  92. });
  93. }
  94. }
  95. }
  96. </script>
  97. <style>
  98. .spinbox {
  99. position: fixed;
  100. display: flex;
  101. justify-content: center;
  102. align-items: center;
  103. height: 100%;
  104. width: 100%;
  105. z-index: 9999
  106. }
  107. .spin {
  108. display: inline-block;
  109. width: 64rpx;
  110. height: 64rpx;
  111. }
  112. .spin:after {
  113. content: " ";
  114. display: block;
  115. width: 46rpx;
  116. height: 46rpx;
  117. margin: 1rpx;
  118. border-radius: 50%;
  119. border: 5rpx solid #409eff;
  120. border-color: #409eff transparent #409eff transparent;
  121. animation: spin 1.2s linear infinite;
  122. }
  123. @keyframes spin {
  124. 0% {
  125. transform: rotate(0deg);
  126. }
  127. 100% {
  128. transform: rotate(360deg);
  129. }
  130. }
  131. .chiaroscuro {
  132. width: 100%;
  133. height: 100%;
  134. background: rgb(194, 207, 214);
  135. animation-duration: 2s;
  136. animation-name: blink;
  137. animation-iteration-count: infinite;
  138. }
  139. @keyframes blink {
  140. 0% {
  141. opacity: .4;
  142. }
  143. 50% {
  144. opacity: 1;
  145. }
  146. 100% {
  147. opacity: .4;
  148. }
  149. }
  150. @keyframes flush {
  151. 0% {
  152. left: -100%;
  153. }
  154. 50% {
  155. left: 0;
  156. }
  157. 100% {
  158. left: 100%;
  159. }
  160. }
  161. .shine {
  162. animation: flush 2s linear infinite;
  163. position: absolute;
  164. top: 0;
  165. bottom: 0;
  166. width: 100%;
  167. background: linear-gradient(to left,
  168. rgba(255, 255, 255, 0) 0%,
  169. rgba(255, 255, 255, .85) 50%,
  170. rgba(255, 255, 255, 0) 100%)
  171. }
  172. </style>