200 lines
4.6 KiB
Vue
200 lines
4.6 KiB
Vue
<template>
|
||
<view v-if="show"
|
||
:style="{width: systemInfo.width + 'px', height: systemInfo.height + 'px', backgroundColor: bgcolor, position: 'absolute', left: 0, top: 0, zIndex: 9998}">
|
||
<view v-for="(item,rect_idx) in skeletonRectLists" :key="rect_idx + 'rect'"
|
||
:class="[loading == 'chiaroscuro' ? 'chiaroscuro' : '']"
|
||
: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'}">
|
||
</view>
|
||
<view v-for="(item,circle_idx) in skeletonCircleLists" :key="circle_idx + 'circle'"
|
||
:class="loading == 'chiaroscuro' ? 'chiaroscuro' : ''"
|
||
: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'}">
|
||
</view>
|
||
<view class="spinbox" v-if="loading == 'spin'">
|
||
<view class="spin"></view>
|
||
</view>
|
||
</view>
|
||
</template>
|
||
|
||
<script>
|
||
// +----------------------------------------------------------------------
|
||
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
|
||
// +----------------------------------------------------------------------
|
||
// | Copyright (c) 2016~2024 https://www.crmeb.com All rights reserved.
|
||
// +----------------------------------------------------------------------
|
||
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
|
||
// +----------------------------------------------------------------------
|
||
// | Author: CRMEB Team <admin@crmeb.com>
|
||
// +----------------------------------------------------------------------
|
||
export default {
|
||
name: "skeleton",
|
||
props: {
|
||
bgcolor: {
|
||
type: String,
|
||
value: '#FFF'
|
||
},
|
||
selector: {
|
||
type: String,
|
||
value: 'skeleton'
|
||
},
|
||
loading: {
|
||
type: String,
|
||
value: 'spin'
|
||
},
|
||
show: {
|
||
type: Boolean,
|
||
value: false
|
||
},
|
||
isNodes: {
|
||
type: Number,
|
||
value: false
|
||
} //控制什么时候开始抓取元素节点,只要数值改变就重新抓取
|
||
},
|
||
data() {
|
||
return {
|
||
loadingAni: ['spin', 'chiaroscuro'],
|
||
systemInfo: {},
|
||
skeletonRectLists: [],
|
||
skeletonCircleLists: []
|
||
}
|
||
},
|
||
watch: {
|
||
isNodes(val) {
|
||
this.readyAction();
|
||
}
|
||
},
|
||
mounted() {
|
||
this.attachedAction();
|
||
},
|
||
methods: {
|
||
attachedAction: function() {
|
||
//默认的首屏宽高,防止内容闪现
|
||
const systemInfo = uni.getSystemInfoSync();
|
||
this.systemInfo = {
|
||
width: systemInfo.windowWidth,
|
||
height: systemInfo.windowHeight
|
||
};
|
||
this.loading = this.loadingAni.includes(this.loading) ? this.loading : 'spin';
|
||
},
|
||
readyAction: function() {
|
||
const that = this;
|
||
//绘制背景
|
||
uni.createSelectorQuery().selectAll(`.${this.selector}`).boundingClientRect().exec(function(res) {
|
||
if(res[0].length>0)
|
||
that.systemInfo.height = res[0][0].height + res[0][0].top;
|
||
});
|
||
|
||
//绘制矩形
|
||
this.rectHandle();
|
||
|
||
//绘制圆形
|
||
this.radiusHandle();
|
||
},
|
||
rectHandle: function() {
|
||
const that = this;
|
||
|
||
//绘制不带样式的节点
|
||
uni.createSelectorQuery().selectAll(`.${this.selector}-rect`).boundingClientRect().exec(function(res) {
|
||
that.skeletonRectLists = res[0];
|
||
});
|
||
|
||
},
|
||
radiusHandle() {
|
||
const that = this;
|
||
|
||
uni.createSelectorQuery().selectAll(`.${this.selector}-radius`).boundingClientRect().exec(function(res) {
|
||
that.skeletonCircleLists = res[0];
|
||
});
|
||
}
|
||
}
|
||
}
|
||
</script>
|
||
|
||
<style>
|
||
.spinbox {
|
||
position: fixed;
|
||
display: flex;
|
||
justify-content: center;
|
||
align-items: center;
|
||
height: 100%;
|
||
width: 100%;
|
||
z-index: 9999
|
||
}
|
||
|
||
.spin {
|
||
display: inline-block;
|
||
width: 64rpx;
|
||
height: 64rpx;
|
||
}
|
||
|
||
.spin:after {
|
||
content: " ";
|
||
display: block;
|
||
width: 46rpx;
|
||
height: 46rpx;
|
||
margin: 1rpx;
|
||
border-radius: 50%;
|
||
border: 5rpx solid #409eff;
|
||
border-color: #409eff transparent #409eff transparent;
|
||
animation: spin 1.2s linear infinite;
|
||
}
|
||
|
||
@keyframes spin {
|
||
0% {
|
||
transform: rotate(0deg);
|
||
}
|
||
|
||
100% {
|
||
transform: rotate(360deg);
|
||
}
|
||
}
|
||
|
||
.chiaroscuro {
|
||
width: 100%;
|
||
height: 100%;
|
||
background: rgb(194, 207, 214);
|
||
animation-duration: 2s;
|
||
animation-name: blink;
|
||
animation-iteration-count: infinite;
|
||
}
|
||
|
||
@keyframes blink {
|
||
0% {
|
||
opacity: .4;
|
||
}
|
||
|
||
50% {
|
||
opacity: 1;
|
||
}
|
||
|
||
100% {
|
||
opacity: .4;
|
||
}
|
||
}
|
||
|
||
@keyframes flush {
|
||
0% {
|
||
left: -100%;
|
||
}
|
||
|
||
50% {
|
||
left: 0;
|
||
}
|
||
|
||
100% {
|
||
left: 100%;
|
||
}
|
||
}
|
||
|
||
.shine {
|
||
animation: flush 2s linear infinite;
|
||
position: absolute;
|
||
top: 0;
|
||
bottom: 0;
|
||
width: 100%;
|
||
background: linear-gradient(to left,
|
||
rgba(255, 255, 255, 0) 0%,
|
||
rgba(255, 255, 255, .85) 50%,
|
||
rgba(255, 255, 255, 0) 100%)
|
||
}
|
||
</style>
|