198 lines
4.2 KiB
Vue
198 lines
4.2 KiB
Vue
<template>
|
|
<view v-if="visible" class="loading-container" @touchmove.stop.prevent="handleTouchMove">
|
|
<view class="loading-content">
|
|
<!-- 刻度点容器 -->
|
|
<view class="clock-container">
|
|
<view v-for="(dot, index) in dots" :key="index" class="clock-dot" :style="{
|
|
transform: `rotate(${index * angle}deg) translateY(-${radius}px)`,
|
|
backgroundColor: getDotColor(index),
|
|
animationDuration: `${duration}ms`,
|
|
animationDelay: `${index * (duration / dotsCount)}ms`
|
|
}"></view>
|
|
</view>
|
|
|
|
<!-- 提示文本 -->
|
|
<text class="loading-text" :class="text?'':'displayNone'" :style="{ color: textColor }">{{ text }}</text>
|
|
</view>
|
|
</view>
|
|
</template>
|
|
|
|
<script>
|
|
export default {
|
|
data() {
|
|
return {
|
|
visible: false,
|
|
dotsCount: 12,
|
|
dotColors: ['#CEF231c2'],
|
|
text: '请稍候...',//文本文字
|
|
textColor: '#FFFFFFde',//文本颜色
|
|
radius: 50,//圆的半径
|
|
duration: 1200,//动画的播放速度
|
|
colorIndex: 0
|
|
}
|
|
},
|
|
computed: {
|
|
// 计算每个点之间的角度
|
|
angle() {
|
|
return 360 / this.dotsCount
|
|
},
|
|
// 生成刻度点数组
|
|
dots() {
|
|
return Array.from({
|
|
length: this.dotsCount
|
|
})
|
|
}
|
|
},
|
|
methods: {
|
|
// 获取刻度点颜色(实现无限循环变色)
|
|
getDotColor(index) {
|
|
// 根据当前颜色索引和刻度点位置计算颜色
|
|
const colorIndex = (index + this.colorIndex) % this.dotColors.length
|
|
return this.dotColors[colorIndex]
|
|
},
|
|
|
|
// 更新颜色索引(实现循环变色)
|
|
updateColorIndex() {
|
|
this.colorIndex = (this.colorIndex + 1) % this.dotColors.length
|
|
},
|
|
|
|
// 显示loading
|
|
show(options) {
|
|
|
|
if(!options){
|
|
options={};
|
|
}
|
|
|
|
this.update(options)
|
|
this.visible = true
|
|
|
|
// 启动颜色循环
|
|
if (!this.colorTimer) {
|
|
this.colorTimer = setInterval(() => {
|
|
this.updateColorIndex()
|
|
}, this.duration / this.dotColors.length)
|
|
}
|
|
},
|
|
|
|
// 隐藏loading
|
|
hide() {
|
|
|
|
this.visible = false
|
|
// 清除颜色循环定时器
|
|
if (this.colorTimer) {
|
|
clearInterval(this.colorTimer)
|
|
this.colorTimer = null
|
|
}
|
|
},
|
|
|
|
// 更新loading配置
|
|
update(options) {
|
|
if(!options){
|
|
options={a:1};
|
|
}
|
|
Object.keys(options).forEach(key => {
|
|
if (this[key] !== undefined) {
|
|
this[key] = options[key]
|
|
}
|
|
})
|
|
|
|
// 如果更新了颜色数组,重置颜色索引
|
|
if (options.dotColors) {
|
|
this.colorIndex = 0
|
|
}
|
|
},
|
|
|
|
// 阻止触摸移动事件
|
|
handleTouchMove() {}
|
|
},
|
|
|
|
beforeDestroy() {
|
|
// 组件销毁前清除定时器
|
|
if (this.colorTimer) {
|
|
clearInterval(this.colorTimer)
|
|
this.colorTimer = null
|
|
}
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style scoped>
|
|
/* 全屏遮罩层 */
|
|
.loading-container {
|
|
position: fixed;
|
|
top: 0;
|
|
left: 0;
|
|
right: 0;
|
|
bottom: 0;
|
|
background-color: #000000c2;
|
|
display: flex;
|
|
justify-content: center;
|
|
align-items: center;
|
|
z-index: 99999999999;
|
|
pointer-events: auto;
|
|
|
|
}
|
|
|
|
/* 内容居中 */
|
|
.loading-content {
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
justify-content: center;
|
|
transform: translateZ(0);
|
|
/* 启用GPU加速 */
|
|
margin-top: -150rpx;
|
|
}
|
|
|
|
/* 刻度容器 */
|
|
.clock-container {
|
|
position: relative;
|
|
width: 200rpx;
|
|
height: 200rpx;
|
|
margin-bottom: 30rpx;
|
|
}
|
|
|
|
/* 单个刻度点 */
|
|
.clock-dot {
|
|
position: absolute;
|
|
top: 50%;
|
|
left: 50%;
|
|
width: 14rpx;
|
|
height: 52rpx;
|
|
border-radius: 12rpx;
|
|
/* margin-top: -4rpx;
|
|
margin-left: -4rpx; */
|
|
transform-origin: 0 0;
|
|
animation: colorScale infinite ease-in-out;
|
|
box-shadow: 0 0 8rpx rgba(0, 0, 0, 0.2);
|
|
}
|
|
|
|
/* 刻度点动画 - 颜色和大小变化 */
|
|
@keyframes colorScale {
|
|
0% {
|
|
opacity: 0.05;
|
|
|
|
}
|
|
|
|
100% {
|
|
opacity: 1;
|
|
|
|
}
|
|
}
|
|
|
|
/* 提示文本 */
|
|
.loading-text {
|
|
font-size: 32rpx;
|
|
font-weight: 400;
|
|
letter-spacing: 1.4rpx;
|
|
text-align: center;
|
|
max-width: 80vw;
|
|
padding: 0 20px;
|
|
line-height: 1.5;
|
|
font-family: 'PingFang SC';
|
|
}
|
|
|
|
.displayNone{
|
|
display: none !important;
|
|
}
|
|
</style> |