index.vue 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  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. // +----------------------------------------------------------------------
  19. // | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
  20. // +----------------------------------------------------------------------
  21. // | Copyright (c) 2016~2024 https://www.crmeb.com All rights reserved.
  22. // +----------------------------------------------------------------------
  23. // | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
  24. // +----------------------------------------------------------------------
  25. // | Author: CRMEB Team <admin@crmeb.com>
  26. // +----------------------------------------------------------------------
  27. export default {
  28. name: "skeleton",
  29. props: {
  30. bgcolor: {
  31. type: String,
  32. value: '#FFF'
  33. },
  34. selector: {
  35. type: String,
  36. value: 'skeleton'
  37. },
  38. loading: {
  39. type: String,
  40. value: 'spin'
  41. },
  42. show: {
  43. type: Boolean,
  44. value: false
  45. },
  46. isNodes: {
  47. type: Number,
  48. value: false
  49. } //控制什么时候开始抓取元素节点,只要数值改变就重新抓取
  50. },
  51. data() {
  52. return {
  53. loadingAni: ['spin', 'chiaroscuro'],
  54. systemInfo: {},
  55. skeletonRectLists: [],
  56. skeletonCircleLists: []
  57. }
  58. },
  59. watch: {
  60. isNodes(val) {
  61. this.readyAction();
  62. }
  63. },
  64. mounted() {
  65. this.attachedAction();
  66. },
  67. methods: {
  68. attachedAction: function() {
  69. //默认的首屏宽高,防止内容闪现
  70. const systemInfo = uni.getSystemInfoSync();
  71. this.systemInfo = {
  72. width: systemInfo.windowWidth,
  73. height: systemInfo.windowHeight
  74. };
  75. this.loading = this.loadingAni.includes(this.loading) ? this.loading : 'spin';
  76. },
  77. readyAction: function() {
  78. const that = this;
  79. //绘制背景
  80. uni.createSelectorQuery().selectAll(`.${this.selector}`).boundingClientRect().exec(function(res) {
  81. if(res[0].length>0)
  82. that.systemInfo.height = res[0][0].height + res[0][0].top;
  83. });
  84. //绘制矩形
  85. this.rectHandle();
  86. //绘制圆形
  87. this.radiusHandle();
  88. },
  89. rectHandle: function() {
  90. const that = this;
  91. //绘制不带样式的节点
  92. uni.createSelectorQuery().selectAll(`.${this.selector}-rect`).boundingClientRect().exec(function(res) {
  93. that.skeletonRectLists = res[0];
  94. });
  95. },
  96. radiusHandle() {
  97. const that = this;
  98. uni.createSelectorQuery().selectAll(`.${this.selector}-radius`).boundingClientRect().exec(function(res) {
  99. that.skeletonCircleLists = res[0];
  100. });
  101. }
  102. }
  103. }
  104. </script>
  105. <style>
  106. .spinbox {
  107. position: fixed;
  108. display: flex;
  109. justify-content: center;
  110. align-items: center;
  111. height: 100%;
  112. width: 100%;
  113. z-index: 9999
  114. }
  115. .spin {
  116. display: inline-block;
  117. width: 64rpx;
  118. height: 64rpx;
  119. }
  120. .spin:after {
  121. content: " ";
  122. display: block;
  123. width: 46rpx;
  124. height: 46rpx;
  125. margin: 1rpx;
  126. border-radius: 50%;
  127. border: 5rpx solid #409eff;
  128. border-color: #409eff transparent #409eff transparent;
  129. animation: spin 1.2s linear infinite;
  130. }
  131. @keyframes spin {
  132. 0% {
  133. transform: rotate(0deg);
  134. }
  135. 100% {
  136. transform: rotate(360deg);
  137. }
  138. }
  139. .chiaroscuro {
  140. width: 100%;
  141. height: 100%;
  142. background: rgb(194, 207, 214);
  143. animation-duration: 2s;
  144. animation-name: blink;
  145. animation-iteration-count: infinite;
  146. }
  147. @keyframes blink {
  148. 0% {
  149. opacity: .4;
  150. }
  151. 50% {
  152. opacity: 1;
  153. }
  154. 100% {
  155. opacity: .4;
  156. }
  157. }
  158. @keyframes flush {
  159. 0% {
  160. left: -100%;
  161. }
  162. 50% {
  163. left: 0;
  164. }
  165. 100% {
  166. left: 100%;
  167. }
  168. }
  169. .shine {
  170. animation: flush 2s linear infinite;
  171. position: absolute;
  172. top: 0;
  173. bottom: 0;
  174. width: 100%;
  175. background: linear-gradient(to left,
  176. rgba(255, 255, 255, 0) 0%,
  177. rgba(255, 255, 255, .85) 50%,
  178. rgba(255, 255, 255, 0) 100%)
  179. }
  180. </style>