第一篇博客,一直不晓得用啥内容填充,简单上一个关于svg的小交互吧;
<!DOCTYPE html>
<html lang="cn">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" href="./css/index.css">
</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 class="arrow-top" points='6,20 20,6 34,20' fill='none' stroke="#fff" stroke-width='2'></polyline>
<line class="middle-line" x1='50%' y1="7" x2='50%' y2='34' stroke="#fff" stroke-width='2'></line>
<polyline class="checkmark" points='8,20 18,30 30,12' fill='none' stroke="#fff" stroke-width='2'></polyline>
</svg>
<div class="progress-bar"></div>
</div>
</main>
<script>
let uploadButton = document.querySelector(".upload-button");
let progressBar = document.querySelector(".upload-button .progress-bar");
let width = uploadButton.getBoundingClientRect().width;
let uploadTime = 1500;
uploadButton.addEventListener('click',()=>{
uploadButton.classList.remove('uploaded');
uploadButton.classList.add('uploading');
setTimeout(()=>{
uploadButton.classList.replace('uploading','uploaded');
},uploadTime)
let start = null
function grow(timestamp){
/*
timestamp:传入的是即将渲染动画帧的时间戳,
start:渲染动画的第一帧,可以理解成HTTP开始请求的时间
*/
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() 告诉浏览器——你希望执行一个动画,并且要求浏览器在下次重绘之前调用指定的回调函数更新动画。该方法需要传入一个回调函数作为参数,该回调函数会在浏览器下一次重绘之前执行
*/
window.requestAnimationFrame(grow)
})
</script>
</body>
</html>
*{
margin: 0;
padding: 0;
box-sizing: border-box;
/* font-family: ; */
}
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: 0;
height: 2px;
background-image: linear-gradient(45deg, #85ffbd,#fffb7d);
bottom: 0;
left: 0;
border-radius: 4px;
}
.upload-button.uploading .middle-line{
stroke-dasharray: 5 2;
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-dasharray: 100 100;
stroke-dashoffset: 100;
animation: 1s linear checkmarkTransform forwards 0.7s;
}
.upload-button.uploaded .middle-line{
transition: 0.3s linear;
opacity: 0;
}
@keyframes dashLoop {
from {
stroke-dashoffset: 0;
}
to{
stroke-dashoffset: 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;
}
}