Files

161 lines
3.1 KiB
Vue

<template>
<view
class="app-loading"
:class="`app-loading--${variant}`"
role="status"
aria-live="polite"
aria-busy="true"
>
<view class="app-loading__emblem" aria-hidden="true">
<image
class="app-loading__seal"
src="/static/assets/foundation/transparent/brand-seal.png"
mode="aspectFit"
/>
<image
class="app-loading__knot"
src="/static/assets/foundation/transparent/auth-divider-knot.png"
mode="aspectFit"
/>
</view>
<text class="app-loading__copy">{{ text }}</text>
<text v-if="description" class="app-loading__description">{{
description
}}</text>
</view>
</template>
<script setup>
defineProps({
variant: {
type: String,
default: "page",
validator: (value) => ["page", "section"].includes(value),
},
text: { type: String, default: "正在展开,请稍候…" },
description: { type: String, default: "" },
});
</script>
<style scoped lang="scss">
.app-loading {
z-index: 1;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
color: #62584c;
text-align: center;
}
.app-loading__emblem {
display: flex;
flex-direction: column;
align-items: center;
}
.app-loading__seal {
animation: app-loading-seal-breathe 1.6s ease-in-out infinite;
}
.app-loading__knot {
margin-top: 8rpx;
opacity: 0.72;
animation: app-loading-knot-breathe 1.6s ease-in-out infinite;
}
.app-loading__copy {
font-weight: 500;
letter-spacing: 2rpx;
}
.app-loading__description {
color: #62584c;
line-height: 1.65;
}
.app-loading--page {
min-height: 320rpx;
}
.app-loading--page .app-loading__seal {
width: 132rpx;
height: 136rpx;
}
.app-loading--page .app-loading__knot {
width: 56rpx;
height: 18rpx;
}
.app-loading--page .app-loading__copy {
margin-top: 22rpx;
font-size: clamp(17px, 30rpx, 22px);
}
.app-loading--page .app-loading__description {
margin-top: 14rpx;
font-size: clamp(15px, 24rpx, 18px);
}
.app-loading--section {
min-height: 180rpx;
}
.app-loading--section .app-loading__seal {
width: 88rpx;
height: 90rpx;
}
.app-loading--section .app-loading__knot {
width: 42rpx;
height: 14rpx;
margin-top: 5rpx;
}
.app-loading--section .app-loading__copy {
margin-top: 14rpx;
font-size: clamp(15px, 24rpx, 18px);
}
.app-loading--section .app-loading__description {
margin-top: 10rpx;
font-size: clamp(14px, 22rpx, 17px);
}
@keyframes app-loading-seal-breathe {
0%,
100% {
opacity: 0.82;
transform: scale(0.96);
}
50% {
opacity: 1;
transform: scale(1);
}
}
@keyframes app-loading-knot-breathe {
0%,
100% {
opacity: 0.44;
}
50% {
opacity: 0.76;
}
}
@keyframes app-loading-seal-essential-pulse {
0%,
100% {
opacity: 0.58;
}
50% {
opacity: 1;
}
}
@keyframes app-loading-knot-essential-pulse {
0%,
100% {
opacity: 0.28;
}
50% {
opacity: 0.86;
}
}
@media (prefers-reduced-motion: reduce) {
.app-loading__seal {
animation: none;
transform: none;
}
.app-loading__knot {
animation: none;
transform: none;
}
}
</style>