【功能实现】手写导航栏遇到的问题,opacity占位,display没动画效果,已全部解决

文章讲述了作者在手写顶部导航栏时遇到的问题,包括使用opacity控制显示/隐藏时的占位问题、动画消失及鼠标交互问题。通过引入Animate.css插件和调整CSS、JavaScript,作者提供了详细的解决步骤,包括使用display:none和定时器实现淡入淡出动画控制。
摘要由CSDN通过智能技术生成

手写一个顶部导航栏遇到的问题

前言

手写一个顶部导航栏,最终效果如下:

鼠标移入菜单栏选项后,选项卡淡入动画显示,移出选项卡后淡出

在这里插入图片描述

实现思路

鼠标移入菜单选项后(:hover),将选项卡的opacity变为1 且加入动画淡入效果(但会引出问题一 <元素仍占位>)

遇到的问题

  1. 使用opacity控制选项卡显示/隐藏,会出现占位情况
  2. 使用display: none => block 控制选项卡显示/隐藏,动画消失
  3. 鼠标经过间隙处,动画提前消失
  4. 鼠标移出不会触发淡出动画

解决流程

问题一:使用opacity控制选项卡显示/隐藏,会出现占位情况

html

 <ul>
   <li>
     <a href="#">菜单一</a>
     <div class="select">
       <div class="select_item">
       	 <a href="">选项一</a>
       </div>
       <div class="select_item">
         <a href="">选项二</a>
       </div>
       <div class="select_item">
       	 <a href="">选项三</a>
       </div>
     </div>
   </li>
   <li>
     <a href="#">菜单二</a>
     <div class="select">
       <div class="select_item">
       	 <a href="">选项一</a>
       </div>
       <div class="select_item">
         <a href="">选项二</a>
       </div>
       <div class="select_item">
       	 <a href="">选项三</a>
       </div>
     </div>
   </li>
</ul>

css

ul {
  display: flex;
  margin-left: 70px;

  li {
    position: relative;
    margin-right: 40px;
    height: 22px;
    font-size: 18px;
    color: rgb(46, 51, 75);
    line-height: 30px;
    cursor: pointer;

    a {
      display: block;
      color: rgb(46, 51, 75);
      &:hover {
      color: rgb(0, 0, 0, 0.8);
      }
    }

    .select {
      opacity: 0;
      width: 250px;
      position: absolute;
      top: 25px;
      margin-top: 10px;
      background-color: #fff;
      z-index: 999999;
      padding: 12px;
      border-radius: 6px;
      font-size: 16px;
      
      .select_item {
        a {
        font-size: 16px;
        line-height: 28px;
        }
      }
    }

    &:hover .select {
      opacity: 1;
      transition: opacity 2s;
     }
   }
}

使用opacity控制选项卡显示/隐藏时,元素会占位,所以导致了鼠标移入选项卡范围内(如下图区域),也会展示选项卡。

在这里插入图片描述

解决方法: 将opacity:0 => opacity: 1 变为 display: none => display: block即可。但是带来了问题二

在这里插入图片描述

问题二:使用display: none => block 控制选项卡显示/隐藏,动画消失

因为transition无法监听display由none变为block,故无法实现动画淡入效果

解决方法:

​ 下载 Animate 插件,一个动画插件,官网地址https://animate.style/,点击右侧选项即可展示动画效果。

在这里插入图片描述

Animate.css插件的基本使用:

  1. 下载

    npm install animate.css --save
    
  2. 注册引用插件

    vue项目将css引入到main.js, react项目将css引入到index.js。

    import 'animate.css'
    
  3. 使用

    给需要动画的元素添加对应动画的类名即可,注意:不管使用哪个效果,都需要添加animate_animated这个类名。

    在这里插入图片描述

​ 此时发现页面一渲染,动画就自动触发,只需定义一个变量,用来控制初始状态/开/ 关,即可。

​ 定义变量showoptions,0表示初始关闭状态,1表示开启(淡入),2表示关闭(淡 出)。修改后,代码如下:

在这里插入图片描述

在这里插入图片描述

问题三:鼠标经过间隙处,动画提前消失

鼠标经过如下区域,由于选项内容由定位实现,脱离了文档流,所以监听mousemove事件的li元素的区域仅仅是"菜单一"这个a标签的区域,所以鼠标移经红色区域fadeout触发,导致用户无法点击选项。

在这里插入图片描述

解决方法:

​ 给菜单一所在的这个元素一个padding-bottom,撑起内容(padding-bottom与选项内容的margin-top相等即可),从而扩大li(监听mousemove事件的元素)的范围。

在这里插入图片描述

问题四:鼠标移出不会触发淡出动画

按照如上写法发现,鼠标移出后并不会触发fadeout淡出动画,是由于在:hover的一瞬间,display重新变成了none,所以看不到淡出动画。

解决方法:

​ 在触发淡出时重新将display变为block即可。

在这里插入图片描述

在这里插入图片描述

此时虽然有淡出效果,但是移出后,display始终为block,只是插件将其隐藏,又出现了占位问题。

解决方法:

​ 在一定时间后(动画完毕)再次将display变为none。

​ 不再需要css的:hover,删除即可

在这里插入图片描述

​ 定义变量isnone用于控制选项卡的显示/隐藏,timer定时器

在这里插入图片描述

在这里插入图片描述

​ 在鼠标移出时,开启定时器,一秒后自动将display变为none

​ 在鼠标移入时,清除定时器,display仍保持block

在这里插入图片描述

至此,已全部实现

最终代码

html

 <ul>
   <li @mousemove="onMousemove" @mouseout="onMouseout">
     <a href="#">菜单一</a>
     <div
           :style="{ display: isnone }"
           :class="
                   showoptions == 0
                   ? 'select'
                   : showoptions == 1
                   ? 'select animate__animated animate__fadeIn'
                   : 'select animate__animated animate__fadeOut'
                  "
       >
       <div class="select_item">
       	 <a href="">选项一</a>
       </div>
       <div class="select_item">
         <a href="">选项二</a>
       </div>
       <div class="select_item">
       	 <a href="">选项三</a>
       </div>
     </div>
   </li>
   ...
</ul>

css

ul {
  display: flex;
  margin-left: 70px;

  li {
    position: relative;
    margin-right: 40px;
    padding-bottom: 10px;
    height: 22px;
    font-size: 18px;
    color: rgb(46, 51, 75);
    line-height: 30px;
    cursor: pointer;

    a {
      display: block;
      color: rgb(46, 51, 75);
      &:hover {
      color: rgb(0, 0, 0, 0.8);
      }
    }

    .select {
      display: none;
      width: 250px;
      height: auto;
      position: absolute;
      top: 25px;
      margin-top: 10px;
      background-color: #fff;
      z-index: 999999;
      padding: 12px;
      border-radius: 6px;
      font-size: 16px;
      
      .select_item {
        a {
          font-size: 16px;
          line-height: 28px;
        }
      }
    }
}

js

// 定义变量
showoptions: 0
isnone: "",
timer: null,

// 鼠标移入、移出事件
onMousemove() {
  this.showoptions = 1
  this.isnone = "block"
  clearTimeout(this.timer)
},
onMouseout() {
  this.showoptions = 2
  this.timer = setTimeout(() => {
    this.isnone = "none"
  }, 800)
},
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

田本初

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值