最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 记录贴-移动端菜单栏效果

    正文概述 掘金(不想差一点的前端菜鸟)   2021-03-16   493

    某次刷掘金UI设计版块看到一个移动端的菜单gif动图,效果如下:

    记录贴-移动端菜单栏效果

    实现过程也不难,最后效果如下:

    记录贴-移动端菜单栏效果

    接下来是代码:

    首先是html结构

    <body>
        <div class="content">
            <div id="main"></div>
            <div id="menu">
                <div class="bar">
                    <div class="item active-item" data-index=1 data-atr="menuLink">
                        <span class="icon">
                            <i class="iconfont icon-70BasicIcons-all-12"></i>
                        </span>
                        <span class="text">home</span>
                    </div>
                    <div class="item" data-index=2 data-atr="menuLink">
                        <span class="icon">
                            <i class="iconfont icon-70BasicIcons-all-13"></i>
                        </span>
                        <span class="text">edit</span>
                    </div>
                    <div class="item" data-index=3 data-atr="menuLink">
                        <span class="icon">
                            <i class="iconfont icon-70BasicIcons-all-05"></i>
                        </span>
                        <span class="text">profile</span>
                    </div>
                </div>
                <div class="active-box-filter"></div>
            </div>
        </div>
    
    </body>
    

    结构说明:

    <div id="menu"> 用fixed固定在页面底部,
    底部的容器实际是<div class="bar">...</bar>使用了flex布局方式
    icon和text分别使用<span>标签包裹起来,方便分别处理CSS效果
    在三个菜单Item之后有一个classactive-box-filterdiv,其实就是gif中的半透明背景

    观察gif效果可以看出:

    • 选中时:icon有像左移动的效果,整个item有一个半透明的背景,并且是从上一个item那里移动过来的,文字出 现

    • 离开时:icon向右归位,半透明背景移动到下一个item,文字渐渐消失

    实现:

    • Item未被选中时,给包裹Icon的span一个translateX(130%),目的是水平往右移动,重叠在text的位置,而包裹text的span则将其opacity设为0,两者都添加一个0.2s的过渡效果transtion
    .icon{
        display: inline-block;
        transform: translateX(130%);
        transition: all .2s ease-in-out;
    }
    .text {
        opacity: 0;
        transition: all .2s ease-in-out;
    }
    

    Item被选中时,将Icon所属span的translateX(-15%),span会水平向左移动,text所属span的opacity设为1

    .active-item .icon{
        transform: translateX(-15%);
    }
    .active-item .text{
        opacity: 1;
    }
    

    上述完成后已经可以实现Icon的移动和Text的渐显

    接下来是半透明背景

    默认选中第一个菜单Item, 选中的item添加一个activeClassactive-item,背景的div的position设为absolute;并且其父元素添加相对位置属性,

    <div class="item active-item" ></div>
    ...
    <div class="active-box-filter"></div>
    
    .active-item{
        color:white;
        transition: all .1s ease-in-out;
    }
    .active-box-filter{
        display: inline-block;
        position: absolute;
        width: 30%;
        height: 54%;
        background-color: rgba(255, 255, 255, 0.2);
        top: 23%;
        left: 2%;
        border-radius: 10px;
       transform: translateX(0px);
       transition: all .3s ease-in-out;
    }
    

    完整的CSS在文章最后

    最后是JS,在html中我给三个菜单Item都分别添加自定义属性data-indexdata-attr,目的无外乎是为了在js操作更加便捷。

    思路:

    • 选中时:判断event的target,如果target上data-attr=="menuLink",表示当前节点currentNode=e.target,否则currentNode=e.target.parentNode
    • 接下来获取菜单Item节点列表,利用data-index比较其和currentNode是否相等,
    • 若相等,则设置activeClass并且修改半透明背景块的水平移动距离translateX

    完整js如下

    <script>
        let barNode = document.querySelector('.bar')
        barNode.addEventListener("click", nodeClick, false)
    
        function nodeClick(e) {
            let currentNode;
            let filterNode = document.querySelector(".active-box-filter")
            if (e.target.dataset.atr == "menuLink") {
                currentNode = e.target;
            } else if (e.target.parentNode.dataset.atr == "menuLink") {
                currentNode = e.target.parentNode
            }
            if (currentNode == undefined) return false;
    
            //childNode是一个NodeList,其自带一个forEach方法
            let childNode = document.querySelectorAll(".item");
            childNode.forEach((node, index) => {
                if (node.dataset.index !== currentNode.dataset.index) {
                    node.className = "item"
                } else {
                    node.className = "item active-item"
                    filterNode.style["transform"] = `translateX(${110*(node.dataset.index-1)}%)`
                }
            })
        }
    </script>
    

    总结:
    整个看下来,其实比较关键的是如何只使用一个半透明背景块做不定距离的移动,笔者尝试过使用一个after伪元素,但其在js计算translate的时候不太方便,弃之,
    最后选择了一个单独的div做处理,并且利用translateX动画结合transtion的过渡,这样就能在视觉上看到背景块的所有运动。

    如果你有更好的方案欢迎交流~~

    完整CSS

    *,
    html,
    body {
        margin: 0;
        padding: 0;
        font-size:16px;
    }
    
    .content {
        position: relative;
    }
    
    #main {
        background-color: #e9ecff;
        min-height: 800px;
    }
    
    #menu {
        background-color: rgb(67, 47, 191);
        position: fixed;
        bottom: 0;
        left: 0;
        height: 4.375rem;
        width: 100%;
    }
    
    
    .bar {
        display: flex;
        width: inherit;
        height: inherit;
        justify-content: space-around;
        align-items: center;
    }
    
    .item {
        width: 5.625rem;
        position: relative;
        text-align: center;
        color:#9a9a9a;
        line-height: 2.81rem;
        transition: all .1s ease-in-out;
    }
    .active-box-filter{
        display: inline-block;
        position: absolute;
        width: 30%;
        height: 54%;
        background-color: rgba(255, 255, 255, 0.2);
        top: 23%;
        left: 2%;
        border-radius: 10px;
       transform: translateX(0px);
       transition: all .3s ease-in-out;
    }
    
    .active-item{
        color:white;
        transition: all .1s ease-in-out;
    }
    
    
    .icon{
        display: inline-block;
        transform: translateX(130%);
        transition: all .2s ease-in-out;
    }
    .text{
        opacity: 0;
        transition: all .2s ease-in-out;
    }
    .active-item .icon{
        transform: translateX(-15%);
    }
    .active-item .text{
        opacity: 1;
    }
    

    起源地下载网 » 记录贴-移动端菜单栏效果

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元