【CSS案例】下载进度条
【CSS案例】下载进度条
HTML代码
<div class="loader" onclick="render()"><div class="per">0</div>
</div>
CSS代码
body {background: #292929;--val: 360deg;--bcolor1: #17a2ff;--bcolor2: #343434;
}
.loader {margin: 150px auto;height: 400px;width: 400px;/* 两个角度设为一样,渐变才会有割裂感 */background: conic-gradient(var(--bcolor1) var(--val), var(--bcolor2) var(--val));position: relative;border-radius: 50%;
}
.loader::before { /* 半透明蒙版 */content: '';height: 84%;width: 84%;border-radius: 50%;background: rgba(41, 41, 41, .85);position: absolute;inset: 8%;
}
.loader::after {content: '';height: 400px;width: 400px;background: var(--bcolor1);position: absolute;clip-path: polygon(45% 25%, 55% 25%, 55% 55%, 65% 55%, 50% 75%, 35% 55%, 45% 55%); /* 下箭头 */
}
.loader.tick::after {clip-path: polygon(42% 63%, 79% 36%, 42% 70%, 25% 53%); /* 对号 */
}
.per {width: 100%;opacity: 0;overflow: hidden;color: var(--bcolor1);text-align: center;top: 60%;position: absolute;font-size: 4rem;font-weight: bolder;
}
.per::after {content: '%';
}
.min::after {animation: flash 1s;transform: scale(0.6) translate(0, -20%);
}
/* 下箭头缩放并上移 */
@keyframes flash {from {transform: scale(1) translate(0, 0);}to {transform: scale(0.6) translate(0, -20%);}
}
.per-show {animation: per .5s;opacity: 1;
}
/* 显示百分比 */
@keyframes per {from {opacity: 0;}to {opacity: 1;}
}
JS代码
let deg = 0, i = 0;
let loader = document.querySelector('.loader'); // 进度条
let per = document.querySelector('.per'); // 百分比
let colorLib = { // 颜色库wineRed: 'f8094b',darkGray: '343434',green: '00ff2b'
};
let middleColor = []; // 中间色
function render() {if (deg === 0) {loader.classList.add('min'); // 【下箭头】缩小per.classList.add('per-show'); // 显示【百分比】// 修改【圆锥渐变】颜色loader.style.setProperty('--bcolor1', '#' + colorLib.wineRed);loader.style.setProperty('--bcolor2', '#' + colorLib.darkGray);}// 计算百分比per.innerHTML = Math.floor(100 / 360 * deg);loader.style.setProperty('--val', deg + 'deg');if (deg > 360) { // 进度条加载完成loader.classList.add('tick'); // 【下箭头】改为【对号】// 计算渐变残差// middleColor = gradient(colorLib.wineRed, colorLib.green, 100);// changeColor(); // 渐变改色} else {deg++window.requestAnimationFrame(render)}
}
优化
由于在进度条加载完,突然由红变绿,感觉颜色很突兀,所以加了渐变。
/* 修改颜色(渐变) */
function changeColor() {if (middleColor.length > i) {loader.style.setProperty('--bcolor1', '#' + middleColor[i])i++window.requestAnimationFrame(changeColor)}
}
/* 十六进制 转 [128, 128, 128] */
function hexToRgb(hex) {var rgb = [];for (var i = 1; i < 7; i += 2) {rgb.push(parseInt("0x" + hex.slice(i, i + 2)));}return rgb;
}
/* [128, 128, 128] 转 十六进制 */
function rgbToHex(r, g, b) {var hex = ((r << 16) | (g << 8) | b).toString(16);return new Array(Math.abs(hex.length - 7)).join("0") + hex;
}
/* 计算两个颜色的差值,用于实现渐变 */
function gradient(startColor, endColor, step) {//将hex转换为rgbvar sColor = hexToRgb(startColor),eColor = hexToRgb(endColor);//计算R\G\B每一步的差值var rStep = (eColor[0] - sColor[0]) / step;gStep = (eColor[1] - sColor[1]) / step;bStep = (eColor[2] - sColor[2]) / step;var gradientColorArr = [];for (var i = 0; i < step; i++) {//计算每一步的hex值gradientColorArr.push(rgbToHex(parseInt(rStep * i + sColor[0]), parseInt(gStep * i + sColor[1]), parseInt(bStep * i + sColor[2])));}return gradientColorArr;
}
JavaScript计算渐变方法来源
思考
加载完成的渐变效果我思考了两种方法,可惜都碰了壁。
想法①:使用CSS动画修改颜色变量。
结果:CSS动画只能使用变量,不能修改变量。
想法②:【clip-path】样式,如果能反选抠图,就能下面那样使用CSS动画修改颜色。
.loader.tick {animation: coll .5s;
}
@keyframes coll {from {background: #f8094b;}to {background: #00ff2b;}
}
结果:【clip-path】样式没法反选抠图
这个效果我是优化的别人的方案。
B站:带进度动画的动画下载按钮
不知道还有没有优化的空间,希望大佬多多指教。(ΦωΦ)
优化 2024-06-14
使用Houdini自定义CSS样式优化
/* 自定义样式 */
@property --bcolor {syntax: '<color>'; /* 选填<color>、<angle> */initial-value: #00ff2b;inherits: false;
}
/* 修改颜色 */
.loader.tick {color: var(--bcolor);background: var(--bcolor);animation: coll .5s;
}
@keyframes coll {from {--bcolor: #f8094b;}to {--bcolor: #00ff2b;}
}
.tick .per {color: var(--bcolor);
}
.loader.tick::after {background: var(--bcolor);
}