Files
mbmanager-dashboard/src/components/LoadingCheck.vue
T
2026-08-30 11:25:31 +03:30

73 lines
1.9 KiB
Vue

<!-- LoadingCheck.vue -->
<script setup>
import { computed, onMounted, onUnmounted, ref, watch } from 'vue';
const props = defineProps({
isComplete: {
type: Boolean,
default: false
},
size: {
type: Number,
default: 24
}
});
const dashOffset = ref(0);
let animationFrame = null;
const circleStyle = computed(() => ({
strokeDasharray: '60 60',
strokeDashoffset: props.isComplete ? '60' : String(dashOffset.value),
transition: props.isComplete ? 'all 0.2s ease-in-out' : 'none',
transformOrigin: 'center',
transform: `rotate(${props.isComplete ? -90 : 0}deg)`
}));
const checkStyle = computed(() => ({
opacity: props.isComplete ? 1 : 0,
strokeDasharray: 20,
strokeDashoffset: props.isComplete ? 0 : 20,
transition: 'all 0.3s ease-in-out',
transitionDelay: '0.2s'
}));
let startTime = null;
const animate = (timestamp) => {
if (!startTime) startTime = timestamp;
dashOffset.value = (timestamp - startTime) / 10;
animationFrame = requestAnimationFrame(animate);
};
watch(
() => props.isComplete,
(newValue) => {
if (newValue && animationFrame) {
cancelAnimationFrame(animationFrame);
animationFrame = null;
}
}
);
onMounted(() => {
if (!props.isComplete) {
animationFrame = requestAnimationFrame(animate);
}
});
onUnmounted(() => {
if (animationFrame) {
cancelAnimationFrame(animationFrame);
}
});
</script>
<template>
<div class="inline-flex items-center justify-center">
<svg :width="size" :height="size" viewBox="0 0 24 24" class="transform transition-transform duration-500">
<circle cx="12" cy="12" r="8" fill="none" stroke="currentColor" stroke-width="2" class="text-blue-500" :style="circleStyle" />
<path d="M8 12l3 3l5-5" fill="none" stroke="currentColor" stroke-width="2" class="text-green-500" :style="checkStyle" />
</svg>
</div>
</template>