直接看代码吧
/**
* 创建带百分比数字的进度遮罩层
* @param {Object} [options] 配置参数
* @param {string} [options.maskBg='rgba(0,0,0,0.5)'] 遮罩背景色
* @param {string} [options.progressColor='#4CAF50'] 进度条颜色
* @param {string} [options.textColor='#fff'] 文字颜色
* @param {number} [options.height=4] 进度条高度(px)
* @param {number} [options.fontSize=14] 字体大小(px)
* @param {number} [options.duration=3000] 完成总时长(ms)
* @param {boolean} [options.autoStart=true] 是否自动开始
* @returns {Object} 控制对象
*/
function createLoadingMask(options = {}) {
const config = {
maskBg: 'rgba(0,0,0,0.5)',
progressColor: '#4CAF50',
textColor: '#fff',
height: 4,
fontSize: 14,
duration: 3000,
autoStart: true,
zIndex: 9999,
...options
};
// 创建元素
const container = document.createElement('div');
const progress = document.createElement('div');
const percentText = document.createElement('span');
// 容器样式
Object.assign(container.style, {
position: 'fixed',
top: '0',
left: '0',
width: '100vw',
height: '100vh',
backgroundColor: config.maskBg,
zIndex: config.zIndex,
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
justifyContent: 'center',
gap: '10px',
backdropFilter: 'blur(2px)' // 毛玻璃效果(可选)
});
// 进度条样式
Object.assign(progress.style, {
width: '0%',
height: `${config.height}px`,
backgroundColor: config.progressColor,
borderRadius: `${config.height / 2}px`,
transition: 'width 0.1s linear',
maxWidth: '80%',
position: 'relative'
});
// 百分比文字样式
Object.assign(percentText.style, {
color: config.textColor,
fontSize: `${config.fontSize}px`,
fontFamily: 'Arial, sans-serif',
textShadow: '0 1px 2px rgba(0,0,0,0.5)',
position: 'absolute',
left: '50%',
transform: 'translateX(-50%)',
top: '-25px'
});
// 组装结构
progress.appendChild(percentText);
container.appendChild(progress);
document.body.appendChild(container);
// 进度控制逻辑
let startTime = null;
let requestId = null;
if (config.autoStart) {
requestAnimationFrame(animateProgress);
}
let currentProgress = 0;
// 修改后的动画函数
function animateProgress(timestamp) {
if (!startTime) startTime = timestamp;
const elapsed = timestamp - startTime;
const targetProgress = Math.min(elapsed / config.duration, 1) * 100;
// 优先使用手动设置的进度
const progressPercent = Math.min(
config.manualProgress !== undefined ? config.manualProgress : targetProgress,
100
);
// 更新进度条和文字
progress.style.width = `${progressPercent}%`;
percentText.textContent = `${Math.round(progressPercent)}%`;
// 检测是否完成
if (progressPercent >= 100 && config.onComplete) {
config.onComplete();
} else if (elapsed < config.duration && !config.manualProgress) {
requestId = requestAnimationFrame(animateProgress);
}
}
return {
mask: container,
progress,
start() {
if (!requestId) {
startTime = null;
requestAnimationFrame(animateProgress);
}
},
stop() {
if (requestId) {
cancelAnimationFrame(requestId);
requestId = null;
}
},
remove: function() {
this.stop();
document.body.removeChild(container);
if (config.onRemove) config.onRemove();
},
setProgress(percent, animated = false) {
if (percent < 0) percent = 0;
if (percent > 100) percent = 100;
// 更新状态
currentProgress = percent;
config.manualProgress = percent;
// 更新显示
progress.style.width = `${percent}%`;
percentText.textContent = `${Math.round(percent)}%`;
// 停止当前动画
if (!animated) {
this.stop();
}
// 触发完成回调(如果达到100%)
if (percent >= 100 && config.onComplete) {
config.onComplete();
}
}
};
}
使用方法:
// 基础用法
const loader = createLoadingMask();
// 自定义样式用法
const customLoader = createLoadingMask({
maskBg: 'rgba(255,255,255,0.9)',
progressColor: '#2196F3',
textColor: '#2196F3',
fontSize: 18,
height: 6,
duration: 5000,
onComplete: () => {
alert('任务完成!');
customLoader.remove();
}
});
// 手动控制示例
setTimeout(() => {
customLoader.stop();
// customLoader.start(); // 继续进度
}, 2500);
// 立即跳转到100%(无动画)
customLoader.setProgress(100);
// 跳转到75%(带动画过渡)
customLoader.setProgress(75, true);