index.html代码
Segmented Progress Bar
适用浏览器:Chrome、FireFox、360、搜狗、Opera、傲游. 不支持Windows版Safari、IE8及以下浏览器。
来源:站长素材
css代码:
* {
border: 0;
box-sizing: border-box;
margin: 0;
padding: 0;
}
:root {
--hue: 223;
--bg: hsl(var(--hue),10%,90%);
--fg: hsl(var(--hue),10%,10%);
--primary: hsl(var(--hue),90%,55%);
--disabled: hsl(var(--hue),10%,75%);
font-size: calc(16px + (24 - 16) * (100vw - 320px) / (1280 - 320));
}
body, button {
font: 1em/1.5 Hind, sans-serif;
}
body {
background: var(--bg);
color: var(--fg);
height: 100vh;
display: grid;
place-items: center;
}
button {
background: hsl(var(--hue),90%,55%);
border-radius: 0.2em;
color: #fff;
cursor: pointer;
margin: auto;
padding: 0.5em 1em;
position: relative;
left: 50%;
transform: translateX(-50%);
text-align: center;
transition: background 0.15s linear;
}
button:hover {
background: hsl(var(--hue),90%,45%);
}
.sp {
--incTrans: 0.1; /* in seconds */
display: block;
margin-bottom: 1.5em;
overflow: visible;
width: 12.75em;
height: 1.5em;
}
.sp__bar, .sp__hub {
stroke: var(--disabled);
}
.sp__hub--done, .sp__dot--done {
transition: r 0.2s cubic-bezier(0,0,0.33,1.67);
}
.sp__hub--done {
r: 10px;
}
.sp__hub--done ~ .sp__bar-fill {
transition: all calc(1s * var(--incTrans)) linear;
}
.sp__bar-fill, .sp__hub-fill {
stroke: var(--primary);
}
.sp__bar-fill {
stroke-dasharray: 40 40;
stroke-dashoffset: 40;
}
.sp__hub-fill {
stroke-dasharray: 0 62.8 0;
visibility: hidden;
}
.sp__hub-fill--done {
stroke-dasharray: 31.4 0 31.4;
transition: all 0.2s 0.2s ease-out;
visibility: visible;
}
.sp__dot {
fill: var(--primary);
}
.sp__dot--done {
r: 4px;
transition-delay: 0.4s;
}
.status {
margin-bottom: 4.5em;
text-align: center;
}
@media (prefers-color-scheme: dark) {
:root {
--bg: hsl(var(--hue),10%,10%);
--fg: hsl(var(--hue),10%,90%);
--primary: hsl(var(--hue),90%,65%);
--disabled: hsl(var(--hue),10%,30%);
}
}
JavaScript 代码:
document.addEventListener("DOMContentLoaded",() => {
const spb = new SegmentedProgress(".sp",".status");
});
class SegmentedProgress {
constructor(svgQS,statusQS) {
this.svgEl = document.querySelector(svgQS);
this.statusEl = document.querySelector(statusQS);
this.pct = 0;
this.part = 0;
this.parts = 4;
this.timeout = null;
this.init();
let resetBtn = document.getElementById("reset");
if (resetBtn)
resetBtn.addEventListener("click",this.reset.bind(this));
}
init() {
this.updateStatus("加载中…");
this.timeout = setTimeout(this.nextPart.bind(this),750);
}
reset() {
this.pct = 0;
this.part = 0;
// undo all colored strokes
for (let p = 1; p <= this.parts; ++p) {
this.fillBar(p,this.pct);
this.fillCircle(p,true);
}
clearTimeout(this.timeout);
this.init();
}
run() {
if (this.part < this.parts) {
// increment
if (this.pct < 100) {
this.inc(10);
let svgCS = window.getComputedStyle(this.svgEl),
incTrans = (svgCS.getPropertyValue("--incTrans") * 1e3) || 0;
this.timeout = setTimeout(this.run.bind(this),incTrans);
} else {
this.nextPart();
}
}
}
inc(amt) {
this.pct += amt;
if (this.pct >= 100)
this.pct = 100;
this.fillBar(this.part,this.pct);
}
fillBar(part,pct) {
if (this.svgEl) {
let bar = this.svgEl.querySelector(`[data-bar='${part}']`);
if (bar) {
let offset = 40 * (1 - this.pct / 100);
bar.style.strokeDashoffset = offset;
}
}
}
fillCircle(part,unfill = false) {
let dot = this.svgEl.querySelector(`[data-dot='${part}']`),
hub = this.svgEl.querySelector(`[data-hub='${part}']`),
hubFill = this.svgEl.querySelector(`[data-hub-fill='${part}']`);
if (unfill === true) {
if (dot)
dot.classList.remove("sp__dot--done");
if (hub)
hub.classList.remove("sp__hub--done");
if (hubFill)
hubFill.classList.remove("sp__hub-fill--done");
} else {
if (dot)
dot.classList.add("sp__dot--done");
if (hub)
hub.classList.add("sp__hub--done");
if (hubFill)
hubFill.classList.add("sp__hub-fill--done");
}
}
nextPart() {
this.pct = 0;
// next part’s circle
++this.part;
this.fillCircle(this.part);
// display the message
let msg = "";
if (this.part < this.parts)
msg = `\u0044ownloading ${this.part}/${this.parts - 1}…`;
else
msg = "完成!";
this.updateStatus(msg);
// delay for next bar
let hubTotalTrans = 600;
this.timeout = setTimeout(this.run.bind(this),hubTotalTrans);
}
updateStatus(msg) {
if (this.statusEl)
this.statusEl.textContent = msg;
}
}
适用浏览器:Chrome、FireFox、360、搜狗、Opera、傲游. 不支持Windows版Safari、IE8及以下浏览器。
效果图: