likes
comments
collection
share

手撸一个Switch开关组件

作者站长头像
站长
· 阅读数 16

一、前言

手撸系列又来了,这次咱们来撸一个Switch开关组件,废话不多说,咱们立刻发车。

二、使用效果

手撸一个Switch开关组件

三、实现分析

首先我们先不想它的这个交互效果,我们就实现“不合格”时的一个静态页面,静态页面大致如下:

手撸一个Switch开关组件

3.1、静态页面

html结构如下:

    <div class="switch-box">                                 <!-- 整个组件的最外层 -->
        <div class="switch-handle"></div>                    <!-- 小球 -->
        <div class="switch-content">                         <!-- 小球下面的内容 -->
            <span class="buhege">不合格</span>
        </div>
    </div>

css样式如下:

    .switch-box {
        position: relative;
        box-sizing: border-box;
        width: 94px;
        height: 32px;
        overflow: hidden;
        border-radius: 40px;
        background-color: #FF5735;
    }
    .switch-handle {
        position: absolute;
        width: 30px;
        height: 30px;
        background-color: #fff;
        border-radius: 50%;
        top: 50%;
        transform: translate(0, -50%);
    }
    .switch-content {
        width: 100%;
        height: 100%;
        box-sizing: border-box;
        display: flex;
        align-items: center;
        justify-content: flex-end;
        color: #FFFFFF;
        font-size: 16px;
        padding-right: 10px;
    }

3.2、小球滚动

静态页面我们现在是有了,我们现在先想办法让它动起来,最常见的办法就是改变小球的transform样式,代码如下:

    let startStatus = '不合格';
    function click1 (){
        let handle = document.querySelector('.switch-handle');
        if (handle && startStatus == '不合格'){
            // 向右平移
            handle.style.transform = 'translate(64px, -50%)';
            startStatus = '合格';
            return
        }
        if (handle && startStatus == '合格'){
            // 向左平移
            handle.style.transform = 'translate(0, -50%)';
            startStatus = '不合格';
            return
        }
    }

html结构如下:

    <div class="switch-box">
        <div class="switch-handle"></div>
        <div class="switch-content" onclick="click1()">  <!-- +++++新增代码 -->
            <span class="buhege">不合格</span>
        </div>
    </div>

现在我们实现了小球位置的改变(效果如下),但是我们发现,现在小球的位置都是瞬间就改变了,没有任何的过渡效果,这样给用户的感觉像是交互不太好的感觉。

手撸一个Switch开关组件

添加过渡效果:

    .switch-handle {
        position: absolute;
        width: 30px;
        height: 30px;
        background-color: #fff;
        border-radius: 50%;
        top: 50%;
        transform: translate(0, -50%);
        transition: all .3s;               +++++++++ 新增加的代码
    }
    // 其余代码都不变

添加过渡效果后的效果如下(明显的丝滑):

手撸一个Switch开关组件

3.3、改变底色

这块没啥好说的,就是当小球的位置发生改变后,背景颜色也要跟着相应改变,代码如下:

    function click1 (){
        let handle = document.querySelector('.switch-handle');
        // ++++++新增代码
        let contentBackground = document.querySelector('.switch-box');
        if (handle && startStatus == '不合格'){
            handle.style.transform = 'translate(64px, -50%)';
            startStatus = '合格';
            // ++++++++ 新增代码
            contentBackground.style.background = '#18B681';
            return
        }
        if (handle && startStatus == '合格'){
            handle.style.transform = 'translate(0, -50%)';
            startStatus = '不合格';
            contentBackground.style.background = '#FF5735';
            return
        }
    }

效果如下:

手撸一个Switch开关组件

3.4、改变文字

这个跟改变背景色其实也差不多,就是小球滚动时,动态的改变innerHTML,代码如下:

// 其余代码都一样,核心代码如下:
if (handle && startStatus == '不合格'){
    document.querySelector('span').innerHTML = '合格';
    return
}
if (handle && startStatus == '合格'){
    document.querySelector('span').innerHTML = '不合格';
    return
}

效果现在是这样的:

手撸一个Switch开关组件

这么看起来"文字"也是瞬间就改变,我们也想要一个文字之间的过渡效果,"合格"把"不合格"给挤掉,或者"不合格"把"合格"挤掉。

为了完成这样的效果,那么此时我们就必须将这2个状态文字都在html里预制上,这也是使用过渡样式的前提,最后呢,通过 transform 与 overflow的配合,完成最后的效果,具体思路如下:

  • 初始化为"不合格"的状态,当点击触发时,需要将"合格"平移至容器内,将"不合格"平移至 容器外
  • 此时的状态为"合格",当点击再次触发时,需要将"合格"还原至原来的位置,将"不合格"平移至 容器内

最终代码如下:

    let startStatus = '不合格';

    function click1 (){
        let handle = document.querySelector('.switch-handle');
        let contentBackground = document.querySelector('.switch-box');
        let hege = document.querySelector('.hege');
        let buhege = document.querySelector('.buhege');
        if (handle && startStatus == '不合格'){
            handle.style.transform = 'translate(64px, -50%)';
            startStatus = '合格';
            hege.style.transform = 'translate(10px, 0)';
            buhege.style.transform = 'translate(52px, 0)';
            contentBackground.style.background = '#18B681';
            return
        }
        if (handle && startStatus == '合格'){
            handle.style.transform = 'translate(0, -50%)';
            startStatus = '不合格';
            hege.style.transform = 'translate(-30px, 0)';
            buhege.style.transform = 'translate(0, 0)';
            contentBackground.style.background = '#FF5735';
            return
        }
    }

html结构如下:

    <div class="switch-box">
        <div class="switch-handle"></div>
        <div class="switch-content" onclick="click1()">
            <span class="hege">合格</span>
            <span class="buhege">不合格</span>
        </div>
    </div>

css如下:

   .switch-box {
        margin-left: 500px;
        margin-top: 100px;
        position: relative;
        box-sizing: border-box;
        width: 94px;
        height: 32px;
        overflow: hidden;
        border-radius: 40px;
        background-color: #FF5735;
    }
    .switch-handle {
        position: absolute;
        width: 30px;
        height: 30px;
        background-color: #fff;
        border-radius: 50%;
        top: 50%;
        transform: translate(0, -50%);
        transition: all .3s;
    }
    .switch-content {
        width: 100%;
        height: 100%;
        box-sizing: border-box;
        display: flex;
        align-items: center;
        justify-content: space-between;
        color: #FFFFFF;
        font-size: 16px;
        padding-right: 10px;
    }
    span {
        font-size: 14px;
        transition: all .3s;
    }
    span[class="hege"] {
        transform: translate(-30px, 0);
    } 

四、最后

好啦,今天的手撸系列就完事了,关于switch开关组件有更好的想法的话,欢迎评论区里讨论,那么下次再见喽