【移动端】菜单的自动展开与收回

前言

为了满足手机上菜单栏随用户移动,菜单的自动展示与隐藏,特此记录


基本原理

在这里插入图片描述

实现逻辑

window.addEventListener(‘scroll’, debouncedScrollHandler) – 监听文档视图滚动事件

document.querySelector(‘.header’) – 选择器匹配元素
创建show和hidden样式,控制展示和隐藏

具体实现

  1. 监听滚动事件
    在这里插入图片描述
  2. 滚动修改逻辑

首先通过选择器选取菜单
监听当前移动高度 scrollTop (下移为负,上移为正)
为了让展示更加丝滑,当移动距离大于菜单栏高度时,修改状态Math.abs(height) > divHeight
判断状态,有三种情况

  1. 当第一次进入页面时,下滑隐藏菜单
  2. 当菜单隐藏时,上滑展示菜单
  3. 当菜单展示时,下滑隐藏菜单
// 滚轮时间 (根据上滑,下滑状态判断是展示还是隐藏)
    scroll () {
      const headerDiv = document.querySelector('.header')

      if (headerDiv) {
        const scrollTop = document.documentElement.scrollTop
        // 移动高度 (下移为负,上移为正)
        // 当上移,下移超过一个导航栏高度时,进行展示修改
        const height = this.lastScrollTop - scrollTop
        const divHeight = headerDiv.clientHeight + 10 // 菜单高度(尽量给足余量)
        const hasHidden = headerDiv.classList.contains('hidden')
        const hasShow = headerDiv.classList.contains('show')

        if (!hasHidden && !hasShow) {
          if (height < 0 && Math.abs(height) > divHeight) {
            headerDiv.classList.add('hidden')
          }
        } else if (hasHidden) {
          if (height > 0 && Math.abs(height) > divHeight) {
            headerDiv.classList.remove('hidden')
            headerDiv.classList.add('show')
          }
        } else if (hasShow) {
          if (height < 0 && Math.abs(height) > divHeight) {
            headerDiv.classList.remove('show')
            headerDiv.classList.add('hidden')
          }
        }
        this.lastScrollTop = scrollTop
      }
    },

这个状态变化是按用户使用逻辑判断的,实际上可以精简为两种,
上滑 - 展示菜单
下滑 - 隐藏菜单

if (height > 0 && Math.abs(height) > divHeight) {
          hasHidden && headerDiv.classList.remove('hidden')
          !hasShow && headerDiv.classList.add('show')
        } else if (height < 0 && Math.abs(height) > divHeight) {
          !hasHidden && headerDiv.classList.add('hidden')
          hasShow && headerDiv.classList.remove('show')
        }

其他知识

这样我们已经完成了菜单的展示和隐藏,但是还可以通过一些优化让他展示的更为丝滑

  1. 动画设置 – 在样式里使用动画,达到缓慢展开和收起的效果
.hidden {
  animation: menu-disable 1s;
  transform: translateY(-30px);
}

.show {
  animation: menu-show 1s;
}

@keyframes menu-disable {
  0% {
    transform: none;
  }

  100% {
    transform: translateY(-30px);
  }
}

@keyframes menu-show {
  0% {
    transform: translateY(-30px);
  }

  100% {
    transform: none;
  }
}
  1. 防抖监听

因为scroll会实时监听状态的改变,所以用户每移动一次屏幕,就是调用一次scroll方法,就可能修改一次状态,所以使用上就有一种抖动的感觉.(不过使用上面的高度判断逻辑后,不会那么明显)


在使用sroll方法的时候,套一个防抖函数,就可以解决此问题

 // 定义一个防抖函数
    debounce (func, wait) {
      let timeout;
      return function () {
        const context = this, args = arguments;
        clearTimeout(timeout);
        timeout = setTimeout(() => func.apply(context, args), wait);
      };
    },
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值