You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

200 lines
7.5 KiB
Vue

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<template>
<view v-if="loading" :style="{
width: windowWinth + 'px',
height: windowHeight + 'px',
backgroundColor: bgColor,
position: 'absolute',
left: left + 'px',
top: top + 'px',
zIndex: 9998,
overflow: 'hidden'
}"
@touchmove.stop.prevent>
<view v-for="(item, index) in RectNodes" :key="$u.guid()" :class="[animation ? 'skeleton-fade' : '']" :style="{
width: item.width + 'px',
height: item.height + 'px',
backgroundColor: elColor,
position: 'absolute',
left: (item.left - left) + 'px',
top: (item.top - top) + 'px'
}"></view>
<view v-for="(item, index) in circleNodes" :key="$u.guid()" :class="animation ? 'skeleton-fade' : ''" :style="{
width: item.width + 'px',
height: item.height + 'px',
backgroundColor: elColor,
borderRadius: item.width/2 + 'px',
position: 'absolute',
left: (item.left - left) + 'px',
top: (item.top - top) + 'px'
}"></view>
<view v-for="(item, index) in filletNodes" :key="$u.guid()" :class="animation ? 'skeleton-fade' : ''" :style="{
width: item.width + 'px',
height: item.height + 'px',
backgroundColor: elColor,
borderRadius: borderRadius + 'rpx',
position: 'absolute',
left: (item.left - left) + 'px',
top: (item.top - top) + 'px'
}"></view>
</view>
</template>
<script>
/**
* skeleton 骨架屏
* @description 骨架屏一般用于页面在请求远程数据尚未完成时,页面用灰色块预显示本来的页面结构,给用户更好的体验。
* @tutorial https://www.uviewui.com/components/skeleton.html
* @property {String} el-color 骨架块状元素的背景颜色(默认#e5e5e5
* @property {String} bg-color 骨架组件背景颜色(默认#ffffff
* @property {Boolean} animation 骨架块是否显示动画效果默认false
* @property {String Number} border-radius u-skeleton-fillet类名元素对应的骨架块的圆角大小单位rpx默认10
* @property {Boolean} loading 是否显示骨架组件请求完成后将此值设置为false默认true
* @example <u-skeleton :loading="true" :animation="true"></u-skeleton>
*/
export default {
name: "u-skeleton",
props: {
// 需要渲染的元素背景颜色十六进制或者rgb等都可以
elColor: {
type: String,
default: '#e5e5e5'
},
// 整个骨架屏页面的背景颜色
bgColor: {
type: String,
default: '#ffffff'
},
// 是否显示加载动画
animation: {
type: Boolean,
default: false
},
// 圆角值只对类名为u-skeleton-fillet的元素生效为数值不带单位
borderRadius: {
type: [String, Number],
default: "10"
},
// 是否显示骨架true-显示false-隐藏
loading: {
type: Boolean,
default: true
}
},
data() {
return {
windowWinth: 750, // 骨架屏宽度
windowHeight: 1500, // 骨架屏高度
filletNodes: [], // 圆角元素
circleNodes: [], // 圆形元素
RectNodes: [], // 矩形元素
top: 0,
left: 0,
}
},
methods: {
// 查询各节点的信息
selecterQueryInfo() {
// 获取整个父组件容器的高度,当做骨架屏的高度
// 在微信小程序中如果把骨架屏放入组件中使用的话需要调in(this)上下文为父组件才有效
let query = '';
// #ifdef MP-WEIXIN
query = uni.createSelectorQuery().in(this.$parent);
// #endif
// #ifndef MP-WEIXIN
query = uni.createSelectorQuery()
// #endif
query.selectAll('.u-skeleton').boundingClientRect().exec((res) => {
this.windowHeight = res[0][0].height;
this.windowWinth = res[0][0].width;
this.top = res[0][0].bottom - res[0][0].height;
this.left = res[0][0].left;
});
// 矩形骨架元素
this.getRectEls();
// 圆形骨架元素
this.getCircleEls();
// 圆角骨架元素
this.getFilletEls();
},
// 矩形元素列表
getRectEls() {
let query = '';
// 在微信小程序中如果把骨架屏放入组件中使用的话需要调in(this)上下文为父组件才有效
// #ifdef MP-WEIXIN
query = uni.createSelectorQuery().in(this.$parent);
// #endif
// #ifndef MP-WEIXIN
query = uni.createSelectorQuery()
// #endif
query.selectAll('.u-skeleton-rect').boundingClientRect().exec((res) => {
this.RectNodes = res[0];
});
},
// 圆角元素列表
getFilletEls() {
let query = '';
// 在微信小程序中如果把骨架屏放入组件中使用的话需要调in(this)上下文为父组件才有效
// #ifdef MP-WEIXIN
query = uni.createSelectorQuery().in(this.$parent);
// #endif
// #ifndef MP-WEIXIN
query = uni.createSelectorQuery()
// #endif
query.selectAll('.u-skeleton-fillet').boundingClientRect().exec((res) => {
this.filletNodes = res[0];
});
},
// 圆形元素列表
getCircleEls() {
let query = '';
// 在微信小程序中如果把骨架屏放入组件中使用的话需要调in(this)上下文为父组件才有效
// #ifdef MP-WEIXIN
query = uni.createSelectorQuery().in(this.$parent);
// #endif
// #ifndef MP-WEIXIN
query = uni.createSelectorQuery()
// #endif
query.selectAll('.u-skeleton-circle').boundingClientRect().exec((res) => {
this.circleNodes = res[0];
});
}
},
// 组件被挂载
mounted() {
// 获取系统信息
let systemInfo = uni.getSystemInfoSync();
this.windowHeight = systemInfo.windowHeight;
this.windowWinth = systemInfo.windowWidth;
this.selecterQueryInfo();
}
}
</script>
<style lang="scss" scoped>
@import "../../libs/css/style.components.scss";
.skeleton-fade {
width: 100%;
height: 100%;
background: rgb(194, 207, 214);
animation-duration: 1.5s;
animation-name: blink;
animation-timing-function: ease-in-out;
animation-iteration-count: infinite;
}
@keyframes blink {
0% {
opacity: 1;
}
50% {
opacity: 0.4;
}
100% {
opacity: 1;
}
}
</style>