上周六,产品经理钉钉发我一个腾讯公众号的链接,说:“你知道这是怎么实现的吗?”
我内心第一个蹦出的想法是:用filter的grayscale(%),再加个transition过度不就好了🤔。不,肯定不是我想的这么简单。接着我回答:“不知道。”经理说:“去搞下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了。在工作中,我总是容易跑偏旺哥的想法,不知道我这次有没有跑偏,我也不敢问,也不敢说。如果你看到这篇文章,旺哥,在下方留言哈。😄