<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: "PingFang SC", "Microsoft Yahei", sans-serif;
}
main {
display: flex;
align-items: center;
justify-content: center;
background: #222f3e;
height: 100vh;
}
.upload-button {
width: 180px;
height: 60px;
background-image: linear-gradient(160deg, #0093e9, #80d0c7);
border-radius: 8px;
cursor: pointer;
box-shadow: 0 2px 10px rgba(0, 147, 233, 0.28);
position: relative;
display: flex;
align-items: center;
justify-content: center;
overflow: hidden;
}
.upload-button .checkmark {
opacity: 0;
}
.upload-button .progress-bar {
position: absolute;
/* width: 50%; */
height: 2px;
background-image: linear-gradient(45deg, #85ffbd, #fffb7d);
bottom: 0;
left: 0;
border-radius: 4px;
}
.upload-button.uploading .middle-line {
stroke-dasharray: 4 3;
animation: 0.8s linear dashLoop infinite;
}
.upload-button.uploading circle {
animation: 1.5s linear blink infinite;
}
.upload-button.uploaded .arrow-top {
animation: 1s linear arrowTransform forwards;
}
.upload-button.uploaded .checkmark {
opacity: 1;
stroke-dashoffset: 100;
stroke-dasharray: 100 100;
animation: 1s linear checkMarkTransform forwards 0.5s;
}
.upload-button.uploaded .middle-line {
transition: 0.3s linear;
opacity: 0;
}
@keyframes dashLoop {
from {
stroke-dasharray: 0;
}
to {
stroke-dasharray: 7;
}
}
@keyframes blink {
from {
opacity: 1;
}
50% {
opacity: 0.5;
}
to {
opacity: 1;
}
}
@keyframes arrowTransform {
from {
stroke-dasharray: 100 100;
stroke-dashoffset: 0;
}
to {
stroke-dasharray: 100 100;
stroke-dashoffset: -100;
}
}
@keyframes checkMarkTransform {
from {
stroke-dasharray: 100 100;
stroke-dashoffset: 100;
}
to {
stroke-dasharray: 100 100;
stroke-dashoffset: 0;
}
}
</style>
</head>
<body>
<main>
<div class="upload-button ">
<svg class="arrow" width="40" height="40" viewBox="0 0 40 40">
<circle cx="50%" cy="50%" r="19" fill="none" stroke="#fff" stroke-width="2" ></circle>
<polyline points="6,20 20,6 34,20" fill="none" stroke="#fff" stroke-width="2" class="arrow-top"></polyline>
<line x1="50%" y1="7" x2="50%" y2="34" stroke="#fff" stroke-width="2" class="middle-line"></line>
<polyline points="8,20 18,30 30 12" stroke="#fff" stroke-width="2" fill="none" class="checkmark"></polyline>
</svg>
<div class="progress-bar">
</div>
</div>
</main>
<script>
var uploadButton = document.querySelector(".upload-button");
var progressBar = document.querySelector(".upload-button .progress-bar");
let width = uploadButton.getBoundingClientRect().width;
let uploadTime = 5000;
uploadButton.addEventListener("click", () => {
uploadButton.classList.remove("uploaded");
uploadButton.classList.add("uploading");
setTimeout(() => {
uploadButton.classList.replace("uploading", "uploaded")
}, uploadTime);
function grow(timestamp) {
if (!start) start = timestamp;
let progress = timestamp - start;
progressBar.style.width = `${Math.min(width * (progress /uploadTime),width)}px`;
if (progress < uploadTime) {
window.requestAnimationFrame(grow)
}
}
window.requestAnimationFrame(grow)
})
</script>
</body>
</html>
效果图: