index.vue 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  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] && 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. that.skeletonCircleLists = res[0];
  91. });
  92. }
  93. }
  94. }
  95. </script>
  96. <style>
  97. .spinbox {
  98. position: fixed;
  99. display: flex;
  100. justify-content: center;
  101. align-items: center;
  102. height: 100%;
  103. width: 100%;
  104. z-index: 9999
  105. }
  106. .spin {
  107. display: inline-block;
  108. width: 64rpx;
  109. height: 64rpx;
  110. }
  111. .spin:after {
  112. content: " ";
  113. display: block;
  114. width: 46rpx;
  115. height: 46rpx;
  116. margin: 1rpx;
  117. border-radius: 50%;
  118. border: 5rpx solid #409eff;
  119. border-color: #409eff transparent #409eff transparent;
  120. animation: spin 1.2s linear infinite;
  121. }
  122. @keyframes spin {
  123. 0% {
  124. transform: rotate(0deg);
  125. }
  126. 100% {
  127. transform: rotate(360deg);
  128. }
  129. }
  130. .chiaroscuro {
  131. width: 100%;
  132. height: 100%;
  133. background: rgb(194, 207, 214);
  134. animation-duration: 2s;
  135. animation-name: blink;
  136. animation-iteration-count: infinite;
  137. }
  138. @keyframes blink {
  139. 0% {
  140. opacity: .4;
  141. }
  142. 50% {
  143. opacity: 1;
  144. }
  145. 100% {
  146. opacity: .4;
  147. }
  148. }
  149. @keyframes flush {
  150. 0% {
  151. left: -100%;
  152. }
  153. 50% {
  154. left: 0;
  155. }
  156. 100% {
  157. left: 100%;
  158. }
  159. }
  160. .shine {
  161. animation: flush 2s linear infinite;
  162. position: absolute;
  163. top: 0;
  164. bottom: 0;
  165. width: 100%;
  166. background: linear-gradient(to left,
  167. rgba(255, 255, 255, 0) 0%,
  168. rgba(255, 255, 255, .85) 50%,
  169. rgba(255, 255, 255, 0) 100%)
  170. }
  171. </style>