近期在网上冲浪的时候,发现了极氪网站上的一个效果,就是点击按钮,给车辆换色的效果。
下面是汽车的效果:
打开极氪汽车官网,并使用 Wappalyzer浏览器插件查看网站所使用的技术组成。
如下:
分析可知,使用了 GSAP 这个库,那就好办了。
The GreenSock Animation Platform (GSAP)是一个功能十分强大的动画平台,可以帮助我们实现大部分的动画需求,构建高性能的、适用于所有主要浏览器的高性能动画;GSAP非常的灵活,可以在任何框架上处理页面能够所有通过js改变的元素,不仅可以对div的css属性进行动画,还是SVG、React、Vue、WebGL,甚至和Threejs一起使用。
我们使用最简单的方式来实现:HTML+CSS3+JS
1.首先,获取基本的图片等资源
2。设置样式,让汽车图片都重叠在一起
3.引入GSAP库,添加点击事件
打开VSCODE,创建好项目,内容结构如下:
<div class="wrap">
<!-- 汽车 -->
<div class="main">
<img src="./pubilc/img/car/ap_bg_1.webp">
<img src="./pubilc/img/car/ap_bg_2.webp">
<img src="./pubilc/img/car/ap_bg_3.webp">
<img src="./pubilc/img/car/ap_bg_4.webp">
<img src="./pubilc/img/car/ap_bg_5.webp">
<img src="./pubilc/img/car/ap_bg_6.webp">
</div>
<!-- 按钮 -->
<ul class="tabs">
<li><img src="./pubilc/img/btn/ap_btn_1.webp"></li>
<li><img src="./pubilc/img/btn/ap_btn_2.webp"></li>
<li><img src="./pubilc/img/btn/ap_btn_3.webp"></li>
<li><img src="./pubilc/img/btn/ap_btn_4.webp"></li>
<li><img src="./pubilc/img/btn/ap_btn_5.webp"></li>
<li><img src="./pubilc/img/btn/ap_btn_6.webp"></li>
</ul>
</div>
设置样式:
<style>
*{
padding: 0;
margin: 0;
}
.main img{
position: absolute;
left: 0;
width: 100%;
bottom: 0;
}
.tabs{
width: 100%;
display: flex;
justify-content: center;
align-items: center;
position: absolute;
bottom: 100px;
}
.tabs li{
list-style: none;
margin-right: 20px;
}
.tabs li img{
width: 30px;
height: 30px;
cursor: pointer;
border-radius: 50%;
}
</style>
此时看到的样式是这样的:
此时点击车辆下方的按钮是没有任何反应的,因为还没有给按钮添加上点击事件。 使用 CSS 中的 clip-path:polygon ,clip-path 属性使用裁剪方式创建元素的可显示区域, polygon:属性为多点连成线,可实现任意由点连成线的图形。
配合 GSAP 实现动画,使用 GSAP 中的自定义 fromTo 属性,如下:
gsap.fromTo(mainImg[index],
{ 'clip-path':'polygon(100% 0%, 100% 0%, 100% 100%, 100% 100%)' },
{ duration:1, 'clip-path':'polygon(0% 0%, 100% 0%, 100% 100%, 0% 100%)' });
分析下这段代码,括号中的百分比数字代表X,Y轴,寻找坐标点来绘制图形(多个圆在一个角是百分比数值在同一位置),如下:
完整的点击事件如下:
<script src="https://cdn.jsdelivr.net/npm/gsap@3.12/dist/gsap.min.js"></script>
<script>
//获取main 所有图片
const mainImg = document.querySelectorAll('.main img');
//获取tabs 所有li
const tabsLi = document.querySelectorAll('.tabs li');
//获取tabs class
const tabs = document.getElementsByClassName('tabs')[0];
let i = 0;
tabsLi.forEach((item,index) => {
item.addEventListener('click',() => {
//让对应的汽车图片index提高
mainImg[index].style.zIndex = ++i;
//给按钮动态添加z-index
tabs.style.zIndex = ++i;
// 汽车图片颜色进入
gsap.fromTo(mainImg[index],
{ 'clip-path':'polygon(100% 0%, 100% 0%, 100% 100%, 100% 100%)' },
{ duration:1, 'clip-path':'polygon(0% 0%, 100% 0%, 100% 100%, 0% 100%)' });
})
})
</script>
此时效果就出来了,这里要说明一下,如果不设置 tabs.style.zIndex,按钮的层级会被车辆图片给覆盖掉,从而消失,因为车辆图片的层级高于按钮层级。
完整代码,方便直接获取运行:
<!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>
*{
padding: 0;
margin: 0;
}
.main img{
position: absolute;
left: 0;
width: 100%;
bottom: 0;
}
.tabs{
width: 100%;
display: flex;
justify-content: center;
align-items: center;
position: absolute;
bottom: 100px;
}
.tabs li{
list-style: none;
margin-right: 20px;
}
.tabs li img{
width: 30px;
height: 30px;
cursor: pointer;
border-radius: 50%;
}
</style>
</head>
<body>
<div class="wrap">
<!-- 汽车 -->
<div class="main">
<img src="./pubilc/img/car/ap_bg_1.webp">
<img src="./pubilc/img/car/ap_bg_2.webp">
<img src="./pubilc/img/car/ap_bg_3.webp">
<img src="./pubilc/img/car/ap_bg_4.webp">
<img src="./pubilc/img/car/ap_bg_5.webp">
<img src="./pubilc/img/car/ap_bg_6.webp">
</div>
<!-- 按钮 -->
<ul class="tabs">
<li><img src="./pubilc/img/btn/ap_btn_1.webp"></li>
<li><img src="./pubilc/img/btn/ap_btn_2.webp"></li>
<li><img src="./pubilc/img/btn/ap_btn_3.webp"></li>
<li><img src="./pubilc/img/btn/ap_btn_4.webp"></li>
<li><img src="./pubilc/img/btn/ap_btn_5.webp"></li>
<li><img src="./pubilc/img/btn/ap_btn_6.webp"></li>
</ul>
</div>
<script src="https://cdn.jsdelivr.net/npm/gsap@3.12/dist/gsap.min.js"></script>
<script>
//获取main 所有图片
const mainImg = document.querySelectorAll('.main img');
//获取tabs 所有li
const tabsLi = document.querySelectorAll('.tabs li');
//获取tabs class
const tabs = document.getElementsByClassName('tabs')[0];
let i = 0;
tabsLi.forEach((item,index) => {
item.addEventListener('click',() => {
//让对应的汽车图片index提高
mainImg[index].style.zIndex = ++i;
//给按钮动态添加z-index
tabs.style.zIndex = ++i;
// 汽车图片颜色进入
gsap.fromTo(mainImg[index],
{ 'clip-path':'polygon(100% 0%, 100% 0%, 100% 100%, 100% 100%)' },
{ duration:1, 'clip-path':'polygon(0% 0%, 100% 0%, 100% 100%, 0% 100%)' });
})
})
</script>
</body>
</html>
到这里就结束了,这是我实现的思路,当然还有别的方法来实现车辆换色效果,可以在评论中讨论,希望我的代码对你有所帮助!