fix: 加载优化

This commit is contained in:
Gsh
2025-07-20 21:01:41 +08:00
parent 76717c4f8a
commit b5489711ec
3 changed files with 124 additions and 191 deletions

View File

@@ -18,6 +18,94 @@
content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no"> content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no">
<style>
/* 全局样式 */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
/* 加载动画样式 */
.loader-container {
position: fixed;
inset: 0;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
background: #fff;
z-index: 1000;
transition: opacity 0.5s ease;
}
.loader-title {
font-size: clamp(1.5rem, 3vw, 2.5rem);
font-weight: bold;
margin-bottom: 0.5rem;
letter-spacing: -0.02em;
}
.loader-subtitle {
font-size: 0.875rem;
color: #555;
margin-bottom: 1.5rem;
}
.loader-logo {
font-size: 3rem;
margin-bottom: 1.5rem;
display: flex;
justify-content: center;
}
.pulse-box {
width: 32px;
height: 32px;
background: #000;
display: inline-block;
transform-origin: center;
animation: pulse 1.2s infinite ease-in-out;
}
@keyframes pulse {
0% {
transform: scale(1) rotate(0deg);
opacity: 1;
}
50% {
transform: scale(1.2) rotate(45deg);
opacity: 0.8;
}
100% {
transform: scale(1) rotate(90deg);
opacity: 1;
}
}
.loader-text {
font-size: 1.5rem;
font-weight: bold;
margin-bottom: 1rem;
}
.loader-progress-bar {
width: 90%;
max-width: 400px;
height: 8px;
background: #f0f0f0;
border-radius: 4px;
overflow: hidden;
}
.loader-progress {
height: 100%;
width: 0%;
background: #000;
transition: width 0.3s ease-out;
}
</style>
</head> </head>
@@ -34,177 +122,36 @@
<div id="progress-bar" class="loader-progress"></div> <div id="progress-bar" class="loader-progress"></div>
</div> </div>
</div> </div>
<!-- 加载进度脚本:放在 main.ts 之前,保证先执行 -->
<script>
// 立即执行函数改为更简单的写法,减少解析时间
(function(){
const bar = document.getElementById('progress-bar');
const text = document.getElementById('progress-text');
let progress = 0;
function update() {
progress = Math.min(progress + 2 + Math.random() * 3, 95);
bar.style.width = progress + '%';
text.textContent = Math.floor(progress) + '%';
if(progress < 95) requestAnimationFrame(update);
}
update();
window.finishLoading = function() {
bar.style.width = '100%';
text.textContent = '100%';
setTimeout(() => {
document.getElementById('loader').style.opacity = '0';
setTimeout(() => document.getElementById('loader').remove(), 500);
}, 300);
};
})();
</script>
<div id="app"></div> <div id="app"></div>
<style>
/* 全局样式 */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
/* 加载动画样式 */
.loader-container {
position: fixed;
inset: 0;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
background: #fff;
z-index: 1000;
transition: opacity 0.5s ease;
}
.loader-title {
font-size: clamp(1.5rem, 3vw, 2.5rem);
font-weight: bold;
margin-bottom: 0.5rem;
letter-spacing: -0.02em;
}
.loader-subtitle {
font-size: 0.875rem;
color: #555;
margin-bottom: 1.5rem;
}
.loader-logo {
font-size: 3rem;
margin-bottom: 1.5rem;
display: flex;
justify-content: center;
}
.pulse-box {
width: 32px;
height: 32px;
background: #000;
display: inline-block;
transform-origin: center;
animation: pulse 1.2s infinite ease-in-out;
}
@keyframes pulse {
0% {
transform: scale(1) rotate(0deg);
opacity: 1;
}
50% {
transform: scale(1.2) rotate(45deg);
opacity: 0.8;
}
100% {
transform: scale(1) rotate(90deg);
opacity: 1;
}
}
.loader-text {
font-size: 1.5rem;
font-weight: bold;
margin-bottom: 1rem;
}
.loader-progress-bar {
width: 90%;
max-width: 400px;
height: 8px;
background: #f0f0f0;
border-radius: 4px;
overflow: hidden;
}
.loader-progress {
height: 100%;
width: 0%;
background: #000;
transition: width 0.3s ease-out;
}
</style>
<script>
// 加载动画逻辑
// document.addEventListener('DOMContentLoaded', function () {
const loader = document.getElementById('loader');
const progressBar = document.getElementById('progress-bar');
const progressText = document.getElementById('progress-text');
let progress = 0;
let loadingInterval = null;
let isVueReady = false;
// 注册全局事件监听器用于接收Vue的加载完成信号生产环境没有用所以放到app.vue处理
window.addEventListener('vue-ready', function () {
isVueReady = true;
completeLoading();
});
// 开始模拟加载
function startLoading() {
const targetProgress = 95;
const intervalTime = 50; // 50毫秒更新一次
// 计算每次递增的进度值,使用更快的初始速度
let increment = calculateIncrement();
// 开始加载动画
loadingInterval = setInterval(() => {
if (progress>=targetProgress)
{
increment=0;
}
progress += increment;
// 如果进度达到95%或者Vue已经准备好
if (isVueReady) {
// progress = 100;
clearInterval(loadingInterval);
completeLoading();
}
// updateProgress(progress);
}, intervalTime);
}
// 计算动态递增速率,初始较快,后期较慢
function calculateIncrement() {
// 如果已经检测到Vue正在加载加快进度
if (window.Vue) {
return 3;
}
// 首次访问海外地址可能较慢
return 1;
}
// 更新进度条和文本
function updateProgress(value) {
progressBar.style.width = `${value}%`;
progressText.textContent = `${Math.round(value)}%`;
}
// 完成加载并隐藏动画
function completeLoading() {
// 确保进度是100%
// updateProgress(100);
// 淡出加载动画
setTimeout(() => {
loader.style.opacity = '0';
setTimeout(() => {
loader.style.display = 'none';
}, 500);
}, 300);
}
// 启动加载动画
startLoading();
// });
</script>
<script async type="module" src="/src/main.ts"></script> <script async type="module" src="/src/main.ts"></script>
</body> </body>

View File

@@ -1,27 +1,5 @@
<script setup lang="ts"> <script setup lang="ts">
onMounted(() => {
// completeLoading();
// const event = new Event('vue-ready');
// window.dispatchEvent(event);
completeLoading();
});
// 完成加载并隐藏动画
function completeLoading() {
const loader = document.getElementById('loader');
const progressBar = document.getElementById('progress-bar');
const progressText = document.getElementById('progress-text');
// 确保进度是100%
progressBar!.style.width = `${100}%`;
progressText!.textContent = `${Math.round(100)}%`;
// 淡出加载动画
setTimeout(() => {
//loader!.style.opacity = '100';
setTimeout(() => {
loader!.style.display = 'none';
}, 500);
}, 300);
}
</script> </script>
<template> <template>

View File

@@ -9,18 +9,26 @@ import store from './stores';
import './styles/index.scss'; import './styles/index.scss';
import 'virtual:uno.css'; import 'virtual:uno.css';
import 'element-plus/dist/index.css'; import 'element-plus/dist/index.css';
// SVG插件配置
import 'virtual:svg-icons-register'; import 'virtual:svg-icons-register';
// 创建 Vue 应用
const app = createApp(App); const app = createApp(App);
// 安装插件
app.use(router); app.use(router);
app.use(ElMessage); app.use(ElMessage);
app.use(ElementPlusX); app.use(ElementPlusX);
// 注册ElementPlus所有图标
// 注册图标
for (const [key, component] of Object.entries(ElementPlusIconsVue)) { for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
app.component(key, component); app.component(key, component);
} }
app.use(store); app.use(store);
// 挂载 Vue 应用
// mount 完成说明应用初始化完毕,此时手动通知 loading 动画结束
app.mount('#app'); app.mount('#app');
// 通知 index.html 的 loading 动画进度拉满并淡出
(window as any).finishLoading?.();