Files
FirstUI-vue/components/firstui/fui-skeleton/fui-skeleton.vue
2023-08-17 21:28:49 +08:00

211 lines
4.7 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!--本文件由FirstUI授权予新疆天衡创新研究院有限公司手机号1 86 14 0725 4 9身份证尾号5A07X5专用请尊重知识产权勿私下传播违者追究法律责任-->
<template>
<view class="fui-skeleton__wrap" :style="{background:background,height:height+'px'}" ref="fui_skeleton">
<view class="fui-skeleton__item"
:class="{'fui-skeleton__dark':theme==='dark','fui-skeleton__dark-ani':active && theme==='dark','fui-skeleton__light-ani':active && theme!=='dark'}"
:style="{width: item.width+'px', height:item.height+'px', left: item.left+'px', top: item.top+'px',borderRadius:item.type==='round'?(isNvue?item.width/2+'px':'50%'):'6rpx'}"
v-for="(item,index) in elList" :key="index">
</view>
</view>
</template>
<script>
// #ifdef APP-NVUE
const animation = uni.requireNativePlugin('animation');
// #endif
export default {
name: "fui-skeleton",
emits: ['change'],
props: {
//外层元素class值
outerClass: {
type: String,
default: "fui-skeleton"
},
//需要在骨架元素添加以下class值也可传入自定义class值
//需要做骨架的元素class值包含round表示处理成圆形其他为矩形
selector: {
type: Array,
default () {
return ['fui-round', 'fui-rect']
}
},
//骨架屏背景色
background: {
type: String,
default: "transparent"
},
//骨架屏预载数据,如果传入数据则不动态获取节点信息
preloadList: {
type: Array,
default () {
return []
}
},
//是否展示动画效果
active: {
type: Boolean,
default: true
},
//light、dark
theme: {
type: String,
default: 'light'
}
},
data() {
let isNvue = false
// #ifdef APP-NVUE
isNvue = true
// #endif
return {
isNvue: isNvue,
stop: false,
//round、rect
elList: [],
height: 0
};
},
created() {
const res = uni.getSystemInfoSync();
this.height = res.windowHeight;
if (this.preloadList && this.preloadList.length > 0) {
this.elList = this.preloadList
}
},
mounted() {
// #ifndef APP-NVUE
this.$nextTick(() => {
this.nodesRef(this.outerClass).then((res) => {
if (res && res[0]) {
this.height = res[0].height
}
});
if (!this.preloadList || this.preloadList.length === 0) {
this.selectorQuery()
}
})
// #endif
// #ifdef APP-NVUE
this.$nextTick(() => {
setTimeout(() => {
this._animation(false)
}, 50)
})
// #endif
},
// #ifdef APP-NVUE
// #ifndef VUE3
beforeDestroy() {
this.stop = true;
},
// #endif
// #ifdef VUE3
beforeUnmount() {
this.stop = true;
},
// #endif
// #endif
methods: {
// #ifdef APP-NVUE
_animation(type) {
if (!this.$refs['fui_skeleton'] || this.stop || !this.active) return;
animation.transition(
this.$refs['fui_skeleton'].ref, {
styles: {
opacity: type ? 1 : 0.1
},
duration: 1000, //ms
timingFunction: 'linear',
iterationCount: 'infinite',
needLayout: false,
delay: 0 //ms
}, () => {
this._animation(!type)
}
);
},
// #endif
// #ifndef APP-NVUE
//nvue端暂不支持动态获取节点信息
async selectorQuery() {
let selector = this.selector || []
let nodes = []
for (let item of selector) {
await this.nodesRef(item).then((res) => {
res.map(d => {
d.type = item.indexOf('round') === -1 ? 'rect' : 'round';
})
nodes = nodes.concat(res)
})
}
this.elList = nodes
this.$emit('change', {
nodes: nodes
})
},
async nodesRef(name) {
return await new Promise((resolve, reject) => {
uni.createSelectorQuery()
.selectAll(`.${name}`)
.boundingClientRect((res) => {
if (res) {
resolve(res);
} else {
reject(res)
}
}).exec();
})
}
// #endif
}
}
</script>
<style scoped>
.fui-skeleton__wrap {
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
/* #ifndef APP-NVUE */
width: 100%;
z-index: 900;
/* #endif */
}
.fui-skeleton__item {
position: absolute;
background: #eee;
}
.fui-skeleton__dark {
background: #333;
}
/* #ifndef APP-NVUE */
.fui-skeleton__light-ani {
background: linear-gradient(90deg, #eee 25%, #e6e6e6 37%, #eee 63%);
animation: ani 1.4s ease infinite;
background-size: 400% 100%;
}
.fui-skeleton__dark-ani {
background: linear-gradient(90deg, #333 25%, #555 37%, #333 63%);
animation: ani 1.4s ease infinite;
background-size: 400% 100%;
}
@keyframes ani {
0% {
background-position: 100% 50%
}
100% {
background-position: 0 50%
}
}
/* #endif */
</style>