上周六,产品经理钉钉发我一个腾讯公众号的链接,说:“你知道这是怎么实现的吗?”
经理说:“去搞下SVG,以后可以用这个写动画,这样的话,就不用 JS、CSS这么麻烦了。”
当我去了解并看手册学习过后,我内心更加充满疑问。SVG的优点是图像不会失帧不会不清晰,它的清晰度适合任何屏幕分辨率;比起gif、jpeg、png文件要小很多 ;但缺点是:不是所有的浏览器都支持,即老版的浏览器,老版的手机是不支持的。SVG有点像我上学那会玩的CAD,用坐标点画图。这图一点一点画出来?不可能,这怎么可能一个坐标点一个坐标点描绘出来,只为了一个图片点击变亮的动画??
然后我回去打开链接,F12 打开一看,原来是用了2张图片,一张暗的,一张明亮的图片。当点击时,用animate把暗的图片opacity掉,这时肉眼就只看到明亮的图片。这时,我想吐血,为啥我不一开始就F12,😔。
<section style="height: 0px;">
<svg data-copyright="GL" style="display: inline-block;width: 100%;vertical-align: top;background-position: 0% 0%;background-repeat: no-repeat;background-size:100% 100%;background-attachment: scroll;background-image: url(6402.png);-webkit-tap-highlight-color:transparent;-webkit-user-select:none;" viewBox="0 0 1080 720"></svg>
</section>
<svg data-copyright="GL" style="transform: scale(1);display: inline-block;width: 100%;vertical-align: top;background-size: 100% 100%;background-attachment: scroll;background-image: url(640.png);background-position: 0% 0%;background-repeat: no-repeat no-repeat;" viewBox="0 0 1080 720">
<animate attributeName="opacity" begin="click" dur="3000s" keyTimes="0;0.001;1" values="1;0;0" fill="freeze" restart="whenNotActive"></animate>
</svg>
我想换一种思路实现这个点击图片变亮,用最开始想的filter的grayscale(%),再加个transition过度
先附上效果图
//css
.imgN{
width: 300px;
filter: grayscale(100%);
}
.imgactive{
transition: all 1s ease-in-out;
filter: grayscale(0);
}
//html
<div class="img" ><img class="imgN" src="6402.png" alt=""></div>
<script>
document.querySelector('.imgN').addEventListener('click',function(){
document.querySelector('.imgN').classList.toggle('imgactive')
})
</script>
不用点击,改用hover就更简单了。
//css就搞定了
.fourimg img{
width: 300px;
filter: grayscale(100%);
transition: all 1s ease-in-out;
}
.fourimg img:hover{
filter: grayscale(0);
}
//html
<div class="fourimg">
<img src="6402.png" alt="">
</div>
既然知道了SVG,不来点实际性的实操学习,不靠谱,不踏心。然后我就去了哔哩哔哩找了个视频教程跟着实操下,来附上哔哩哔哩作者的链接www.bilibili.com/video/BV1fJ…。
使用SVG实现丝滑流畅的上传按钮动画
老规矩,先附上效果图
这个思路是,先html用svg画出圆形、打勾、箭头、竖线以及虚线,接着css写样式以及动画,最后用js切换uploaded和uploading两个类,以及控制上传进度条。附上最终代码:
//html
<main>
<div class="upload-button uploaded">
<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>
//css
*{
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 rgb(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-dasharray: 100 100;
stroke-dashoffset: 100;
animation: 1s linear checkmarkTransform forwards 0.5s;
}
.upload-button.uploaded .middle-line{
transform: 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;
}
}
//js
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',function(){
uploadButton.classList.remove('uploaded');
uploadButton.classList.add('uploading');
setTimeout(function(){
uploadButton.classList.replace('uploading','uploaded');
},uploadTime);
//进度条
let star = null;
// timestamp 动画开始的时间戳
function grow(timestamp){
if(!star) star = timestamp;
let progress = timestamp - star; //距离开始时过去了多少毫秒作为进度
//根据 progress 按比例算出 该增加多少宽度 给进度条
// Math.min 如果 宽度超出 按钮的宽度,就直接等于 按钮的宽度
// width * (progress / uploadTime) 过去的毫秒 比上 总的毫秒 再 乘以 按钮宽度 就能算出 当前进度条时多少宽度
progressBar.style.width=`${Math.min(width * (progress / uploadTime),width)}px`;
//如果进度还没有到达 uploadTime ,则继续调用 requestAnimationFrame ,直到大于等于 uploadTime
if(progress < uploadTime){
window.requestAnimationFrame(grow);
}
}
window.requestAnimationFrame(grow);
})
嗯,我想旺哥(产品经理)的想法是:用svg做动画。但一整个下来,我也没觉得svg的动画比js,css简易多,是不是我想的太多,哈哈哈😄,肯定是我懒,不想去搞svg了。在工作中,我总是容易跑偏旺哥的想法,不知道我这次有没有跑偏,我也不敢问,也不敢说。如果你看到这篇文章,旺哥,在下方留言哈。😄