feat: expand square loader set and tune bouncing
This commit is contained in:
parent
dc60c7a123
commit
3b521e9616
@ -12,43 +12,53 @@
|
||||
|
||||
<style scoped>
|
||||
.bouncing-squares-loader {
|
||||
--square-size: 3px;
|
||||
--square-gap: 10px;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, var(--square-size));
|
||||
column-gap: var(--square-gap);
|
||||
align-items: end;
|
||||
width: calc(3 * var(--square-size) + 2 * var(--square-gap));
|
||||
--loader-scale: 0.45;
|
||||
--square-size: 7.6px; /* 7.6 * 0.45 ≈ 3.42px,略大一点 */
|
||||
--square-gap: 8.9px; /* 固定间距,缩放后约 4px */
|
||||
--start-x: 3px;
|
||||
position: relative;
|
||||
width: 40px;
|
||||
height: 20px;
|
||||
transform: scale(var(--loader-scale));
|
||||
transform-origin: center;
|
||||
}
|
||||
|
||||
.square {
|
||||
position: absolute;
|
||||
width: var(--square-size);
|
||||
height: var(--square-size);
|
||||
left: 15%;
|
||||
background-color: var(--claude-text-tertiary);
|
||||
transform-origin: center bottom;
|
||||
animation: bounce-square .5s alternate infinite ease;
|
||||
transform-origin: 50%;
|
||||
animation: bounce-square 0.5s alternate infinite ease;
|
||||
}
|
||||
|
||||
@keyframes bounce-square {
|
||||
0% {
|
||||
transform: translateY(0) scaleX(1.7) scaleY(0.7);
|
||||
top: 20px;
|
||||
height: calc(var(--square-size) * 0.667);
|
||||
transform: scaleX(1.7);
|
||||
}
|
||||
|
||||
40% {
|
||||
transform: translateY(-8px) scaleX(1) scaleY(1);
|
||||
height: var(--square-size);
|
||||
transform: scaleX(1);
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: translateY(-17px) scaleX(1) scaleY(1);
|
||||
top: 0%;
|
||||
}
|
||||
}
|
||||
|
||||
.square:nth-child(1) {
|
||||
left: var(--start-x);
|
||||
}
|
||||
|
||||
.square:nth-child(2) {
|
||||
animation-delay: .2s;
|
||||
left: calc(var(--start-x) + var(--square-size) + var(--square-gap));
|
||||
animation-delay: 0.2s;
|
||||
}
|
||||
|
||||
.square:nth-child(3) {
|
||||
animation-delay: .3s;
|
||||
left: calc(var(--start-x) + (var(--square-size) + var(--square-gap)) * 2);
|
||||
animation-delay: 0.3s;
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -0,0 +1,44 @@
|
||||
<template>
|
||||
<div class="chaotic-orbit-loader"></div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
// Based on Uiverse (dovatgabriel), square-styled
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.chaotic-orbit-loader {
|
||||
--size: 24px;
|
||||
--speed: 1.5s;
|
||||
position: relative;
|
||||
width: var(--size);
|
||||
height: var(--size);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
animation: rotate calc(var(--speed) * 1.667) linear infinite;
|
||||
}
|
||||
|
||||
.chaotic-orbit-loader::before,
|
||||
.chaotic-orbit-loader::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
width: 3px;
|
||||
height: 3px;
|
||||
background: var(--claude-text-tertiary);
|
||||
will-change: transform;
|
||||
}
|
||||
|
||||
.chaotic-orbit-loader::before { animation: orbit var(--speed) linear infinite; }
|
||||
.chaotic-orbit-loader::after { animation: orbit var(--speed) linear calc(var(--speed) / -2) infinite; }
|
||||
|
||||
@keyframes rotate { from { transform: rotate(0deg); } to { transform: rotate(360deg); } }
|
||||
|
||||
@keyframes orbit {
|
||||
0% { transform: translate(12px) scale(.74); opacity:.65; }
|
||||
25% { transform: translate(0) scale(.47); opacity:.3; }
|
||||
50% { transform: translate(-12px) scale(.74); opacity:.65; }
|
||||
75% { transform: translate(0) scale(1); opacity:1; }
|
||||
100% { transform: translate(12px) scale(.74); opacity:.65; }
|
||||
}
|
||||
</style>
|
||||
@ -0,0 +1,70 @@
|
||||
<template>
|
||||
<div class="dot-spinner-loader">
|
||||
<div class="dot"></div>
|
||||
<div class="dot"></div>
|
||||
<div class="dot"></div>
|
||||
<div class="dot"></div>
|
||||
<div class="dot"></div>
|
||||
<div class="dot"></div>
|
||||
<div class="dot"></div>
|
||||
<div class="dot"></div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
// Based on Uiverse (abrahamcalsin), square-styled
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.dot-spinner-loader {
|
||||
--size: 22px;
|
||||
--speed: .9s;
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
width: var(--size);
|
||||
height: var(--size);
|
||||
}
|
||||
|
||||
.dot {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.dot::before {
|
||||
content: "";
|
||||
width: 3px;
|
||||
height: 3px;
|
||||
background: var(--claude-text-tertiary);
|
||||
transform: scale(0);
|
||||
opacity: .5;
|
||||
animation: pulse calc(var(--speed) * 1.111) ease-in-out infinite;
|
||||
}
|
||||
|
||||
.dot:nth-child(2) { transform: rotate(45deg); }
|
||||
.dot:nth-child(2)::before { animation-delay: calc(var(--speed) * -0.875); }
|
||||
.dot:nth-child(3) { transform: rotate(90deg); }
|
||||
.dot:nth-child(3)::before { animation-delay: calc(var(--speed) * -0.75); }
|
||||
.dot:nth-child(4) { transform: rotate(135deg); }
|
||||
.dot:nth-child(4)::before { animation-delay: calc(var(--speed) * -0.625); }
|
||||
.dot:nth-child(5) { transform: rotate(180deg); }
|
||||
.dot:nth-child(5)::before { animation-delay: calc(var(--speed) * -0.5); }
|
||||
.dot:nth-child(6) { transform: rotate(225deg); }
|
||||
.dot:nth-child(6)::before { animation-delay: calc(var(--speed) * -0.375); }
|
||||
.dot:nth-child(7) { transform: rotate(270deg); }
|
||||
.dot:nth-child(7)::before { animation-delay: calc(var(--speed) * -0.25); }
|
||||
.dot:nth-child(8) { transform: rotate(315deg); }
|
||||
.dot:nth-child(8)::before { animation-delay: calc(var(--speed) * -0.125); }
|
||||
|
||||
@keyframes pulse {
|
||||
0%, 100% { transform: scale(0); opacity: .5; }
|
||||
50% { transform: scale(1); opacity: 1; }
|
||||
}
|
||||
</style>
|
||||
@ -0,0 +1,38 @@
|
||||
<template>
|
||||
<div class="jumping-seq-loader">
|
||||
<div class="sq"></div>
|
||||
<div class="sq"></div>
|
||||
<div class="sq"></div>
|
||||
<div class="sq"></div>
|
||||
<div class="sq"></div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
// Based on Uiverse (EddyBel), square-styled
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.jumping-seq-loader {
|
||||
position: relative;
|
||||
display: flex;
|
||||
gap: 5px;
|
||||
}
|
||||
|
||||
.sq {
|
||||
width: 3px;
|
||||
height: 3px;
|
||||
background: var(--claude-text-tertiary);
|
||||
animation: jump 2s ease infinite;
|
||||
}
|
||||
|
||||
.sq:nth-child(2n) { animation-delay: 300ms; }
|
||||
.sq:nth-child(3n) { animation-delay: 600ms; }
|
||||
|
||||
@keyframes jump {
|
||||
0%, 100% { transform: translateY(0); }
|
||||
25% { transform: translateY(-10px) scale(0.66); }
|
||||
50% { transform: translateY(0); }
|
||||
75% { transform: translateY(3px) scale(0.9); }
|
||||
}
|
||||
</style>
|
||||
61
static/src/components/chat/loaders/LeapFrogSquaresLoader.vue
Normal file
61
static/src/components/chat/loaders/LeapFrogSquaresLoader.vue
Normal file
@ -0,0 +1,61 @@
|
||||
<template>
|
||||
<div class="leap-frog-loader">
|
||||
<div class="dot"></div>
|
||||
<div class="dot"></div>
|
||||
<div class="dot"></div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
// Based on Uiverse (dovatgabriel), square-styled
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.leap-frog-loader {
|
||||
--size: 24px;
|
||||
--speed: 2s;
|
||||
position: relative;
|
||||
width: var(--size);
|
||||
height: var(--size);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.dot {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
animation: leap var(--speed) ease infinite;
|
||||
}
|
||||
|
||||
.dot::before {
|
||||
content: "";
|
||||
width: 3px;
|
||||
height: 3px;
|
||||
background: var(--claude-text-tertiary);
|
||||
}
|
||||
|
||||
.dot:nth-child(2) {
|
||||
transform: translateX(calc(var(--size) * 0.4));
|
||||
animation-delay: calc(var(--speed) / -1.5);
|
||||
}
|
||||
|
||||
.dot:nth-child(3) {
|
||||
transform: translateX(calc(var(--size) * 0.8));
|
||||
animation-delay: calc(var(--speed) / -3);
|
||||
}
|
||||
|
||||
@keyframes leap {
|
||||
0% { transform: translateX(0) rotate(0deg); }
|
||||
33.333% { transform: translateX(0) rotate(180deg); }
|
||||
66.666% { transform: translateX(calc(var(--size) * -0.4)) rotate(180deg); }
|
||||
99.999% { transform: translateX(calc(var(--size) * -0.8)) rotate(180deg); }
|
||||
100% { transform: translateX(0) rotate(0deg); }
|
||||
}
|
||||
</style>
|
||||
@ -0,0 +1,61 @@
|
||||
<template>
|
||||
<div class="newton-loader">
|
||||
<div class="dot"></div>
|
||||
<div class="dot"></div>
|
||||
<div class="dot"></div>
|
||||
<div class="dot"></div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
// Based on Uiverse (dovatgabriel), square-styled
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.newton-loader {
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.dot {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 100%;
|
||||
width: 25%;
|
||||
transform-origin: center top;
|
||||
}
|
||||
|
||||
.dot::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 75%;
|
||||
width: 3px;
|
||||
height: 3px;
|
||||
background: var(--claude-text-tertiary);
|
||||
}
|
||||
|
||||
.dot:first-child {
|
||||
animation: swing 1.2s linear infinite;
|
||||
}
|
||||
|
||||
.dot:last-child {
|
||||
animation: swing2 1.2s linear infinite;
|
||||
}
|
||||
|
||||
@keyframes swing {
|
||||
0% { transform: rotate(0deg); animation-timing-function: ease-out; }
|
||||
25% { transform: rotate(70deg); animation-timing-function: ease-in; }
|
||||
50% { transform: rotate(0deg); animation-timing-function: linear; }
|
||||
}
|
||||
|
||||
@keyframes swing2 {
|
||||
0% { transform: rotate(0deg); animation-timing-function: linear; }
|
||||
50% { transform: rotate(0deg); animation-timing-function: ease-out; }
|
||||
75% { transform: rotate(-70deg); animation-timing-function: ease-in; }
|
||||
}
|
||||
</style>
|
||||
@ -0,0 +1,50 @@
|
||||
<template>
|
||||
<div class="orbit-loader">
|
||||
<div class="orbe" style="--index: 0"></div>
|
||||
<div class="orbe" style="--index: 1"></div>
|
||||
<div class="orbe" style="--index: 2"></div>
|
||||
<div class="orbe" style="--index: 3"></div>
|
||||
<div class="orbe" style="--index: 4"></div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
// Based on Uiverse (krlozCJ), square + blur, no glow
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.orbit-loader {
|
||||
--size-loader: 24px;
|
||||
--size-orbe: 3px;
|
||||
width: var(--size-loader);
|
||||
height: var(--size-loader);
|
||||
position: relative;
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
|
||||
.orbe {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
--delay: calc(var(--index) * 0.1s);
|
||||
opacity: calc(1 - calc(0.18 * var(--index)));
|
||||
animation: orbit 1.5s var(--delay) ease-in-out infinite;
|
||||
}
|
||||
|
||||
.orbe::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: var(--size-orbe);
|
||||
height: var(--size-orbe);
|
||||
background: var(--claude-text-tertiary);
|
||||
filter: blur(0.35px);
|
||||
}
|
||||
|
||||
@keyframes orbit {
|
||||
0% {}
|
||||
80% { transform: rotate(360deg); }
|
||||
100% { transform: rotate(360deg); }
|
||||
}
|
||||
</style>
|
||||
@ -0,0 +1,31 @@
|
||||
<template>
|
||||
<div class="shadow-rolling-loader"></div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
// Based on Uiverse (alexruix), square-styled
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.shadow-rolling-loader {
|
||||
--sq: 3px;
|
||||
width: var(--sq);
|
||||
height: var(--sq);
|
||||
position: relative;
|
||||
left: -10px;
|
||||
color: var(--claude-text-tertiary);
|
||||
animation: roll 2s linear infinite;
|
||||
}
|
||||
|
||||
@keyframes roll {
|
||||
0% { box-shadow: 0 0 transparent, 0 0 transparent, 0 0 transparent, 0 0 transparent; }
|
||||
12% { box-shadow: 6px 0 currentColor, 0 0 transparent, 0 0 transparent, 0 0 transparent; }
|
||||
25% { box-shadow: 12px 0 currentColor, 6px 0 currentColor, 0 0 transparent, 0 0 transparent; }
|
||||
36% { box-shadow: 18px 0 currentColor, 12px 0 currentColor, 6px 0 currentColor, 0 0 transparent; }
|
||||
50% { box-shadow: 24px 0 currentColor, 18px 0 currentColor, 12px 0 currentColor, 6px 0 currentColor; }
|
||||
62% { box-shadow: 36px 0 transparent, 24px 0 currentColor, 18px 0 currentColor, 12px 0 currentColor; }
|
||||
75% { box-shadow: 36px 0 transparent, 36px 0 transparent, 24px 0 currentColor, 18px 0 currentColor; }
|
||||
87% { box-shadow: 36px 0 transparent, 36px 0 transparent, 36px 0 transparent, 24px 0 currentColor; }
|
||||
100% { box-shadow: 36px 0 transparent, 36px 0 transparent, 36px 0 transparent, 36px 0 transparent; }
|
||||
}
|
||||
</style>
|
||||
@ -6,6 +6,13 @@ import BouncingSquaresLoader from './BouncingSquaresLoader.vue';
|
||||
import FiveSquaresLoader from './FiveSquaresLoader.vue';
|
||||
import NineGridLoader from './NineGridLoader.vue';
|
||||
import RippleLoader from './RippleLoader.vue';
|
||||
import NewtonCradleSquaresLoader from './NewtonCradleSquaresLoader.vue';
|
||||
import DotSpinnerSquaresLoader from './DotSpinnerSquaresLoader.vue';
|
||||
import OrbitBlurSquaresLoader from './OrbitBlurSquaresLoader.vue';
|
||||
import ShadowRollingSquaresLoader from './ShadowRollingSquaresLoader.vue';
|
||||
import JumpingSequenceSquaresLoader from './JumpingSequenceSquaresLoader.vue';
|
||||
import ChaoticOrbitSquaresLoader from './ChaoticOrbitSquaresLoader.vue';
|
||||
import LeapFrogSquaresLoader from './LeapFrogSquaresLoader.vue';
|
||||
|
||||
// 加载动画池
|
||||
export const loaderPool: Component[] = [
|
||||
@ -15,7 +22,14 @@ export const loaderPool: Component[] = [
|
||||
BouncingSquaresLoader,
|
||||
FiveSquaresLoader,
|
||||
NineGridLoader,
|
||||
RippleLoader
|
||||
RippleLoader,
|
||||
NewtonCradleSquaresLoader,
|
||||
DotSpinnerSquaresLoader,
|
||||
OrbitBlurSquaresLoader,
|
||||
ShadowRollingSquaresLoader,
|
||||
JumpingSequenceSquaresLoader,
|
||||
ChaoticOrbitSquaresLoader,
|
||||
LeapFrogSquaresLoader
|
||||
];
|
||||
|
||||
// 至少间隔多少次后才允许重复(例如 4 表示最近 4 次不重复)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user