Initial project
This commit is contained in:
5
src/components/loading/index.ts
Normal file
5
src/components/loading/index.ts
Normal file
@ -0,0 +1,5 @@
|
||||
import view from "./index.vue";
|
||||
import Toolkit from "~/utils/Toolkit";
|
||||
|
||||
export const Loading = Toolkit.withInstall(view);
|
||||
export default Loading;
|
||||
153
src/components/loading/index.vue
Normal file
153
src/components/loading/index.vue
Normal file
@ -0,0 +1,153 @@
|
||||
<template>
|
||||
<div v-if="visible" class="tui-loading" :class="{ 'filled': filled }" :style="style">
|
||||
<div class="icon">
|
||||
<div
|
||||
class="line"
|
||||
:class="lineClass(i)"
|
||||
v-for="i in 4"
|
||||
:key="i"
|
||||
></div>
|
||||
</div>
|
||||
<div v-if="tips" class="text" v-text="tips"></div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { Toolkit } from "~/index";
|
||||
defineOptions({
|
||||
name: "Loading"
|
||||
});
|
||||
|
||||
const props = withDefaults(defineProps<{
|
||||
tips?: string | boolean;
|
||||
delay?: number;
|
||||
showOn?: boolean;
|
||||
size?: number;
|
||||
filled?: boolean;
|
||||
}>(), {
|
||||
tips: "加载中..",
|
||||
delay: 260,
|
||||
showOn: true,
|
||||
size: 24,
|
||||
filled: false
|
||||
});
|
||||
const { tips, delay, showOn, size, filled } = toRefs(props);
|
||||
|
||||
// ---------- 尺寸参数 ----------
|
||||
|
||||
const style = computed(() => {
|
||||
const base = Math.max(8, size.value);
|
||||
const height = Math.round(base);
|
||||
const width = Math.round(base * (8 / 24));
|
||||
const gap = Math.round(base * (3 / 24));
|
||||
return {
|
||||
"--loading-height": `${height}px`,
|
||||
"--rect-width": `${width}px`,
|
||||
"--rect-gap": `${gap}px`
|
||||
};
|
||||
});
|
||||
|
||||
// ---------- 显示控制 ----------
|
||||
|
||||
const visible = ref<boolean>(false);
|
||||
watch(showOn, async () => await start());
|
||||
|
||||
// ---------- 动画 ----------
|
||||
|
||||
const activeI = ref<number>(0);
|
||||
const timer = ref();
|
||||
const lineClass = (i: number): string => {
|
||||
let clazz = "i" + i;
|
||||
if (activeI.value === i) {
|
||||
clazz += " active";
|
||||
}
|
||||
return clazz;
|
||||
};
|
||||
const start = async () => {
|
||||
if (timer.value) {
|
||||
clearInterval(timer.value);
|
||||
}
|
||||
if (showOn.value) {
|
||||
if (0 < delay.value) {
|
||||
await Toolkit.sleep(delay.value);
|
||||
}
|
||||
if (!showOn.value) {
|
||||
return;
|
||||
}
|
||||
visible.value = true;
|
||||
|
||||
// 动画
|
||||
let direction = 1;
|
||||
timer.value = setInterval(() => {
|
||||
activeI.value = activeI.value + direction;
|
||||
if (4 < activeI.value || activeI.value < 1) {
|
||||
direction *= -1;
|
||||
}
|
||||
}, 120);
|
||||
} else {
|
||||
visible.value = false;
|
||||
}
|
||||
};
|
||||
onMounted(start);
|
||||
onUnmounted(() => {
|
||||
if (timer.value) {
|
||||
clearInterval(timer.value);
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.tui-loading {
|
||||
--h1: calc(var(--loading-height) * (9 / 24));
|
||||
--h2: calc(var(--loading-height) * (14 / 24));
|
||||
--h3: calc(var(--loading-height) * (19 / 24));
|
||||
--h4: var(--loading-height);
|
||||
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
|
||||
&.filled {
|
||||
color: #FFF;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: rgba(0, 0, 0, .3);
|
||||
}
|
||||
|
||||
.icon {
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
|
||||
.line {
|
||||
width: var(--rect-width);
|
||||
background: #BBB;
|
||||
margin-right: var(--rect-gap);
|
||||
|
||||
&.i1 {
|
||||
height: calc(var(--h1))
|
||||
}
|
||||
|
||||
&.i2 {
|
||||
height: calc(var(--h2))
|
||||
}
|
||||
|
||||
&.i3 {
|
||||
height: calc(var(--h3))
|
||||
}
|
||||
|
||||
&.i4 {
|
||||
height: var(--h4)
|
||||
}
|
||||
|
||||
&.active {
|
||||
background: #53BD93;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.text {
|
||||
margin-top: .5rem;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user