skeleton.vue 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341
  1. <template>
  2. <view v-if="show"
  3. :style="{width: systemInfo.width * 2 + 'rpx', height: systemInfo.height * 2 + 'rpx', 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 * 2 + 'rpx', height: item.height * 2 + 'rpx', backgroundColor: 'rgb(194, 207, 214,.3)', position: 'absolute', left: item.left * 2 + 'rpx', top: item.top * 2 + 'rpx'}">
  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 * 2 + 'rpx', height: item.height * 2 + 'rpx', backgroundColor: 'rgb(194, 207, 214,.3)', borderRadius: item.width * 2 + 'rpx', position: 'absolute', left: item.left * 2 + 'rpx', top: item.top * 2 + 'rpx'}">
  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: 'chiaroscuro'
  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. bottom: 35,
  48. dataset: {},
  49. height: 25,
  50. id: "",
  51. left: 15,
  52. right: 65,
  53. top: 10,
  54. width: 50,
  55. }, {
  56. bottom: 72,
  57. dataset: {},
  58. height: 30,
  59. id: "",
  60. left: 15,
  61. right: 360,
  62. top: 42,
  63. width: 345,
  64. }, {
  65. bottom: 232,
  66. dataset: {},
  67. height: 145,
  68. id: "",
  69. left: 15,
  70. right: 360,
  71. top: 87,
  72. width: 345,
  73. }, {
  74. bottom: 436,
  75. dataset: {},
  76. height: 30,
  77. id: "",
  78. left: 15,
  79. right: 360,
  80. top: 406,
  81. width: 345,
  82. }, {
  83. bottom: 596,
  84. dataset: {},
  85. height: 150,
  86. id: "",
  87. left: 15,
  88. right: 183,
  89. top: 446,
  90. width: 168,
  91. }, {
  92. bottom: 519,
  93. dataset: {},
  94. height: 73,
  95. id: "",
  96. left: 188,
  97. right: 360,
  98. top: 446,
  99. width: 172,
  100. }, {
  101. bottom: 596,
  102. dataset: {},
  103. height: 73,
  104. id: "",
  105. left: 188,
  106. right: 360,
  107. top: 523,
  108. width: 172,
  109. }, {
  110. bottom: 793,
  111. dataset: {},
  112. height: 177,
  113. id: "",
  114. left: 15,
  115. right: 360,
  116. top: 616,
  117. width: 345,
  118. }, {
  119. bottom: 1680,
  120. dataset: {},
  121. height: 206,
  122. id: "",
  123. left: 15,
  124. right: 360,
  125. top: 1474,
  126. width: 345,
  127. }],
  128. skeletonCircleLists: [{
  129. "id": "",
  130. "dataset": {},
  131. "left": 27,
  132. "right": 72,
  133. "top": 245,
  134. "bottom": 270,
  135. "width": 45,
  136. "height": 45
  137. },
  138. {
  139. "id": "",
  140. "dataset": {},
  141. "left": 96,
  142. "right": 141,
  143. "top": 245,
  144. "bottom": 270,
  145. "width": 45,
  146. "height": 45
  147. },
  148. {
  149. "id": "",
  150. "dataset": {},
  151. "left": 165,
  152. "right": 210,
  153. "top": 245,
  154. "bottom": 270,
  155. "width": 45,
  156. "height": 45
  157. },
  158. {
  159. "id": "",
  160. "dataset": {},
  161. "left": 234,
  162. "right": 279,
  163. "top": 245,
  164. "bottom": 270,
  165. "width": 45,
  166. "height": 45
  167. },
  168. {
  169. "id": "",
  170. "dataset": {},
  171. "left": 303,
  172. "right": 348,
  173. "top": 245,
  174. "bottom": 270,
  175. "width": 45,
  176. "height": 45
  177. },
  178. {
  179. "id": "",
  180. "dataset": {},
  181. "left": 27,
  182. "right": 72,
  183. "top": 327,
  184. "bottom": 352,
  185. "width": 45,
  186. "height": 45
  187. },
  188. {
  189. "id": "",
  190. "dataset": {},
  191. "left": 96,
  192. "right": 141,
  193. "top": 327,
  194. "bottom": 352,
  195. "width": 45,
  196. "height": 45
  197. },
  198. {
  199. "id": "",
  200. "dataset": {},
  201. "left": 165,
  202. "right": 210,
  203. "top": 327,
  204. "bottom": 352,
  205. "width": 45,
  206. "height": 45
  207. },
  208. {
  209. "id": "",
  210. "dataset": {},
  211. "left": 234,
  212. "right": 279,
  213. "top": 327,
  214. "bottom": 352,
  215. "width": 45,
  216. "height": 45
  217. },
  218. {
  219. "id": "",
  220. "dataset": {},
  221. "left": 303,
  222. "right": 348,
  223. "top": 327,
  224. "bottom": 352,
  225. "width": 45,
  226. "height": 45
  227. }
  228. ]
  229. }
  230. },
  231. watch: {
  232. isNodes(val) {
  233. // this.readyAction();
  234. }
  235. },
  236. mounted() {
  237. this.attachedAction();
  238. },
  239. methods: {
  240. attachedAction: function() {
  241. //默认的首屏宽高,防止内容闪现
  242. const systemInfo = uni.getSystemInfoSync();
  243. this.systemInfo = {
  244. width: systemInfo.windowWidth,
  245. height: systemInfo.windowHeight
  246. };
  247. this.loading = this.loadingAni.includes(this.loading) ? this.loading : 'spin';
  248. }
  249. }
  250. }
  251. </script>
  252. <style>
  253. .spinbox {
  254. position: fixed;
  255. display: flex;
  256. justify-content: center;
  257. align-items: center;
  258. height: 100%;
  259. width: 100%;
  260. z-index: 9999
  261. }
  262. .spin {
  263. display: inline-block;
  264. width: 64rpx;
  265. height: 64rpx;
  266. }
  267. .spin:after {
  268. content: " ";
  269. display: block;
  270. width: 46rpx;
  271. height: 46rpx;
  272. margin: 1rpx;
  273. border-radius: 50%;
  274. border: 5rpx solid #409eff;
  275. border-color: #409eff transparent #409eff transparent;
  276. animation: spin 1.2s linear infinite;
  277. }
  278. @keyframes spin {
  279. 0% {
  280. transform: rotate(0deg);
  281. }
  282. 100% {
  283. transform: rotate(360deg);
  284. }
  285. }
  286. .chiaroscuro {
  287. width: 100%;
  288. height: 100%;
  289. background: rgb(194, 207, 214);
  290. animation-duration: 2s;
  291. animation-name: blink;
  292. animation-iteration-count: infinite;
  293. }
  294. @keyframes blink {
  295. 0% {
  296. opacity: .4;
  297. }
  298. 50% {
  299. opacity: 1;
  300. }
  301. 100% {
  302. opacity: .4;
  303. }
  304. }
  305. @keyframes flush {
  306. 0% {
  307. left: -100%;
  308. }
  309. 50% {
  310. left: 0;
  311. }
  312. 100% {
  313. left: 100%;
  314. }
  315. }
  316. .shine {
  317. animation: flush 2s linear infinite;
  318. position: absolute;
  319. top: 0;
  320. bottom: 0;
  321. width: 100%;
  322. background: linear-gradient(to left,
  323. rgba(255, 255, 255, 0) 0%,
  324. rgba(255, 255, 255, .85) 50%,
  325. rgba(255, 255, 255, 0) 100%)
  326. }
  327. </style>