一、 下载进度
- loading弹窗结构
// loading状态DOM
function setLoading() {
let content = document.querySelector('.loading')
content.innerHTML = ''
content.innerHTML = `
<div class="loading_content">
<div class="contentBox">
<div class="downloadTip">
<div class="tips">下载成功!</div>
<div class="close">
<img src="../img/img1/close.png" alt="">
</div>
</div>
<div class="box">
<div class="tip">预计下载时长10-15s, 请耐心等待</div>
<div class="progress-container">
<div class="progress-bar"></div>
<div class="progress-text"></div>
<div class="particles">
<div class="particle"></div>
<div class="particle"></div>
<div class="particle"></div>
<div class="particle"></div>
<div class="particle"></div>
</div>
</div>
</div>
</div>
</div>
`
}
- loading弹窗样式
.loading_content{
/* display: none; */
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.7);
z-index: 5;
font-size: 15px;
}
.loading_content .contentBox {
display: block;
position: relative;
left: 50%;
top: 50%;
transform: translateX(-50%) translateY(-50%);
width: 337px;
height: 168px;
padding: 20px;
background: url("../img/dialog.png") no-repeat center;
background-size: contain;
}
.loading_content .contentBox .box ,
.loading_content .contentBox .downloadTip{
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
justify-content: flex-start;
}
.loading_content .contentBox .downloadTip {
position: relative;
display: none;
color: #fff;
}
.loading_content .contentBox .downloadTip .close {
position: absolute;
cursor: pointer;
top: 0;
right: 0;
width: 25px!important;
height: 25px!important;
}
.loading_content .contentBox .downloadTip .close img {
width: 100%;
height: 100%;
}
.loading_content .contentBox .downloadTip .tips {
position: relative;
top: 50%;
left: 50%;
width: 100%;
height: 50%;
line-height: 84px;
text-align: center;
transform: translateX(-50%) translateY(-50%);
font-size: 22px;
}
.loading_content .contentBox .box .tip {
width: 100%;
text-align: center;
line-height: 75px;
color: #C9B387;
}
.progress-container {
position: relative;
width: 100%;
max-width: 500px;
height: 20px;
background: radial-gradient(circle, #1b2735, #090a0f);
border-radius: 30px;
overflow: hidden;
box-shadow: 0 8px 20px rgba(0, 0, 0, 0.5);
box-sizing: border-box;
border: 1px solid #313131;
}
.progress-bar {
position: absolute;
top: 0;
left: 0;
height: 100%;
background: linear-gradient(90deg, #c9b386, rgb(146, 24, 22));
border-radius: 30px;
animation: grow 7s ease-in forwards;
box-shadow:
0 0 15px #c9b386,
0 0 30px rgb(146, 24, 22);
}
.progress-bar::before {
content: "";
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 200%;
height: 200%;
background: radial-gradient(circle, rgba(255, 255, 255, 0.15), transparent);
opacity: 0.5;
animation: ripple 15s infinite;
}
.progress-text {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
font-size: 10px;
font-weight: bold;
letter-spacing: 1px;
color: #fff;
text-shadow: 0 2px 4px rgba(0, 0, 0, 0.7);
z-index: 2;
}
.particles {
position: absolute;
width: 100%;
height: 100%;
overflow: hidden;
}
.particle {
position: absolute;
width: 4px;
height: 4px;
background: #fff;
border-radius: 50%;
opacity: 0.6;
animation: float 5s infinite ease-in-out;
}
@keyframes grow {
0% {
width: 0;
}
100% {
width: 99%;
}
}
@keyframes ripple {
0% {
transform: translate(-50%, -50%) scale(0.5);
opacity: 0.7;
}
100% {
transform: translate(-50%, -50%) scale(1.5);
opacity: 0;
}
}
@keyframes float {
0% {
transform: translateY(0) translateX(0);
}
50% {
transform: translateY(-20px) translateX(10px);
}
100% {
transform: translateY(0) translateX(0);
}
}
.particle:nth-child(1) {
top: 10%;
left: 20%;
animation-delay: 0s;
}
.particle:nth-child(2) {
top: 30%;
left: 70%;
animation-delay: 1s;
}
.particle:nth-child(3) {
top: 50%;
left: 50%;
animation-delay: 2s;
}
.particle:nth-child(4) {
top: 80%;
left: 40%;
animation-delay: 1.5s;
}
.particle:nth-child(5) {
top: 90%;
left: 60%;
animation-delay: 2.5s;
}
- 开始显示loading
// 开始动画
function loadingStart() {
let text = document.querySelector('.progress-text')
text.innerText = '0%'
let flag = 0
timer = setInterval(() => {
if (text.innerText == '99%') {
clearInterval(timer)
return
}
flag += 7
if (flag == 98) {
flag = 99
}
let data = flag
text.innerText = `${data}%`
}, 500)
}
- 结束loading状态
}
// 结束动画
function loadingDone() {
timer && clearInterval(timer)
// 下载完成
$('.progress-text').html('100%')
$('.progress-bar').css('animation', 'unset')
$('.progress-bar').css('width', '100%')
setTimeout(() => {
// 结果页面显示,loading页面隐藏
$('.box').css('display', 'none')
$('.downloadTip').css('display', 'block')
$('.close').click(function () {
$('.loading').html('')
});
}, 1500)
}
二、 跨域下载与 自定义名称
主要通过请求获取blob来进行下载
- 获取blob
// 异步下载任务
function getBlob(url) {
return new Promise(resolve => {
try {
const xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
xhr.responseType = 'blob';
xhr.onload = () => {
if (xhr.status === 200) {
resolve(xhr.response);
} else {
window.location.href = url;
$('.loading').html('')
}
};
xhr.send();
} catch (error) {
window.location.href = url;
$('.loading').html('')
}
});
}
- 下载与命名
function downloadHandler(blob, url, code) {
let name = url.split('/').pop()
var link = document.createElement('a');
link.href = window.URL.createObjectURL(blob);
if (code) {
// .exe替换成code+.exe
link.download = name.replace(/\.exe$/, '_' + code + '.exe')
} else {
link.download = name
}
link.click();
}