利用JS构造函数实现的导航特效-附带两种效果

134 阅读2分钟

利用构造函数 写的 导航特效

我正在参加「码上掘金挑战赛」详情请看:码上掘金挑战赛来了!

🦖我是Sam9029,一个前端

Sam9029的掘金主页:Sam9029的掘金主页

`🐱‍🐉🐱‍🐉恭喜你,若此文你认为写的不错,不要吝啬你的赞扬,求收藏,求评论,求一个大大的赞!👍


效果及源码

导航移动变化特效(两种特效)-构造函数 - 码上掘金 (juejin.cn)

一个构造函数 NavSlide

普通效果--移动效果

请添加图片描述


伸长拉伸效果--滑动效果

请添加图片描述

  • 原理:
    • 利用 offset系列API(注意要配合定位使用,详情见HTML DOM offsetLeft 属性-菜鸟教程 注意其注意: offsetParent 元素是一个指向最近的(指包含层级上的最近)包含该元素的定位元素或者最近的元素。
    • html结构div#navContainer > nav > ul > li > a 另外 div.moveShadow 作为阴影块
    • div#navContainer 相对定位 ,div.moveShadow绝对定位
    • 根据鼠标移入的目标元素的offsetLeft,与当前阴影的offsetLeft的差值(可为正负)判断左右移动方向

JS源码---完整的构造函数源码

/**
 * @param {String} _contianName 导航容器名称
*/
function NavSlide(_contianName) {
  // 获取导航容器盒子
  this.NavSlide = document.querySelector(_contianName)
  // 获取阴影
  this.moveShadow = document.querySelector(`${_contianName} .moveShadow`)
  // 获取导航项目
  this.navUl = document.querySelector(`${_contianName} nav>ul`)
  this.navItemList = document.querySelectorAll(`${_contianName} nav>ul>li`)

  // 下面 元素的 绑定函数 this 指向改变了,预存
  const _navThis =  this

  // effect 效果 函数

  // 普通的浮动效果 //hover
  this.hoverEffect = function(){
    for(let i=0;i<_navThis.navItemList.length;i++){
      this.navItemList[i].addEventListener('mouseenter',function(){
        _navThis.navItemList[i].classList.add('liActive')
        _navThis.navItemList[i].firstChild.classList.add('currentItem')
      })
      this.navItemList[i].addEventListener('mouseleave',function(){
        _navThis.navItemList[i].classList.remove('liActive')
        _navThis.navItemList[i].firstChild.classList.remove('currentItem')
      })
    }
  }

  // 伸缩效果 // stretch 伸长
  this.stretchEffect = function(){
    console.log('hi');

    // 初始 阴影
    const moveShadow = _navThis.moveShadow
    moveShadow.style.width = _navThis.navItemList[0].offsetWidth + 'px'
    moveShadow.style.left = _navThis.navItemList[0].offsetLeft + 'px'

    for(let i=0;i<_navThis.navItemList.length;i++){
      const item = _navThis.navItemList[i]
      // 给每一个 li 上 事件
      item.addEventListener('mouseenter',function(e){
        // 清除 以往 li>a 的字体高亮
        for(let i=0;i<_navThis.navItemList.length;i++){
          // 找到 li 内嵌套的 a 元素
          _navThis.navItemList[i].childNodes[0].classList.remove("currentItem")
        }

        // 初始化 事件对象 元素标签本身(li)
        let overItem = e.target

        // 处理滑动 ==== // 判断左右	
        // 利用 鼠标浮动目标元素的overItem.offsetLeft - 阴影moveShadow.offsetLeft 正负判断
        // 正 往左移动
        // 负 往右移动
        // console.log(overItem.offsetLeft - moveShadow.offsetLeft)
        if(overItem.offsetLeft - moveShadow.offsetLeft >0 ){
          // 赋予 阴影 菜单选项的 宽度
          // 伸长
          moveShadow.style.width = (overItem.offsetLeft+overItem.offsetWidth-moveShadow.offsetLeft) + 'px'

          setTimeout(()=>{
            // 缩进
            moveShadow.style.width = overItem.offsetWidth + 'px'
            moveShadow.style.left = overItem.offsetLeft + 'px'
          },200)
        }else{
          // 赋予 阴影 菜单选项的 宽度
          // 伸长
          moveShadow.style.left = overItem.offsetLeft + 'px'
          moveShadow.style.width = (moveShadow.offsetLeft+moveShadow.offsetWidth-overItem.offsetLeft) + 'px'

          setTimeout(()=>{
            // 缩进
            moveShadow.style.width = overItem.offsetWidth + 'px'
          },200)
        }
      })
      // li>a 字体高亮,不处理移除是想保持常亮状态,之下一次移动目标元素,所有在上面li绑定的事件处理
      item.firstElementChild.addEventListener('mouseenter',function(e){
        // 初始化 事件对象 元素标签本身(li) // 找到 li 内嵌套的 a 元素
        e.target.classList.add('currentItem')
      })
    }
  }
}

		
let newNav = new NavSlide('#navContain1')
// 普通鼠标触发效果
// newNav.hoverEffect()  
// 伸长拉伸效果
newNav.stretchEffect()

普通效果

  • 直接使用 css hover 属性实现

伸长拉伸的滑动效果

  • 主要思路是 判断 鼠标滑动时的左右移动 方向判断

  • 处理滑动 - 判断左右

    • 利用 鼠标浮动目标元素的overItem.offsetLeft - 阴影moveShadow.offsetLeft 正负判断
    • 正 往左移动
    • 负 往右移动

🦖我是Sam9029,一个前端,坚信应无所往

文章若有错误,敬请指正🙏

**🐱‍🐉🐱‍🐉恭喜你,都看到这了,求收藏,求评论,求一个大大的赞👍!不过分吧**

Sam9029的掘金主页:Sam9029的掘金主页