前端实现极氪汽车换色

159 阅读3分钟

近期在网上冲浪的时候,发现了极氪网站上的一个效果,就是点击按钮,给车辆换色的效果。

下面是汽车的效果:

汽车.gif 打开极氪汽车官网,并使用 Wappalyzer浏览器插件查看网站所使用的技术组成。

如下:

技术.png

分析可知,使用了 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>

此时看到的样式是这样的:

屏幕截图.png

此时点击车辆下方的按钮是没有任何反应的,因为还没有给按钮添加上点击事件。 使用 CSS 中的 clip-path:polygonclip-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轴,寻找坐标点来绘制图形(多个圆在一个角是百分比数值在同一位置),如下:

动画讲解.png

完整的点击事件如下:

<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,按钮的层级会被车辆图片给覆盖掉,从而消失,因为车辆图片的层级高于按钮层级。

bug.gif

完整代码,方便直接获取运行:

<!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>

到这里就结束了,这是我实现的思路,当然还有别的方法来实现车辆换色效果,可以在评论中讨论,希望我的代码对你有所帮助!