悬停时的导航滑动线 - 当没有项目是“当前”或“选定”时

Posted

技术标签:

【中文标题】悬停时的导航滑动线 - 当没有项目是“当前”或“选定”时【英文标题】:Navigation sliding line on hover - when no item is 'current' or 'selected' 【发布时间】:2018-12-24 12:47:16 【问题描述】:

我的主导航栏上有一条滑动线,因此将线悬停动画/滑动到您从当前位置(应该是当前页面)悬停的项目。

示例:https://codepen.io/moy/pen/Yjqrqo

我遇到的问题是,当菜单项上没有 current_menu_item 类时它会中断。

80% 的时间会有一个“已选择”菜单项,但在某些情况下,当您在条款、隐私、联系(页脚链接)页面上没有可关联的主要导航项时。

理想情况下,当没有选定项目时,我希望线条在悬停时淡入,然后从那里滑动。然后,如果您不单击任何内容并再次离开菜单,则该行将淡出。但我愿意接受建议。

$(function() 
    var $el, leftPos, newWidth, $mainNav = $(".site-nav__list");
    $mainNav.append("<div class='site-nav__line'></div>");
    var $magicLine = $(".site-nav__line");
    $magicLine
        .width($(".current-menu-item").width())
        .css("left", $(".current-menu-item a").position().left)
        .data("origLeft", $magicLine.position().left)
        .data("origWidth", $magicLine.width());

    $(".site-nav__list li a").hover(function() 
        $el = $(this);
        leftPos = $el.position().left;
        newWidth = $el.parent().width();
        $magicLine.stop().animate(
            left: leftPos,
            width: newWidth
        );
    , function() 
        $magicLine.stop().animate(
            left: $magicLine.data("origLeft"),
            width: $magicLine.data("origWidth")
        );
    );
);
/* MIXIN */

@mixin clearfix() 
	
	&:before,
	&:after 
		content: "";
		display: table;
	
	
	&:after 
		clear: both;
	


/* Body */

body 
  background: #f9f9f9;
  margin: 0;
  padding: 5px 0 0;


/* Header */

.page-head 
	background: white;
  border-top: 2px solid #ddd;
	box-sizing: border-box;
  @include clearfix;
	padding: 0 30px;
	position: relative;
	width: 100%;


.page-head__logo 
	background-image: none;
	float: left;
	padding: 0;
	text-shadow: none;
	width: 200px;


/* Nav */

.site-nav 
	display: block;
  float: right;
	text-align: center;
  width: auto;


.site-nav__list 
  list-style: none;
	margin: 0;
	padding: 0;
  position: relative;
  top: auto;
  left: auto;
  width: auto;


.site-nav__list li 
	background: none;
  display: inline-block;
	margin: 0;
	padding-left: 0;
	text-transform: uppercase;
	
	&.current-menu-item 


.site-nav__list a 
	box-sizing: border-box;
	display: block;
	font-weight: 900;
	padding: 30px 15px;
	transition: color .15s;
	text-shadow: none;
  
  &:hover 
    color: red;
  


/* Underline */

.site-nav__line 
  background: red;
  content: "";
  display: block;
  height: 2px;
  position: absolute;
  top: -2px;
  left: 0;
  width: 100%;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<header class="page-head">
    <a href="#" class="page-head__logo">Logo Here </a>
    <nav class="site-nav">
        <ul class="site-nav__list">
            <li class="site-nav__item current-menu-item"><a href="#" class="site-nav__link">Home</a></li>
            <li class="site-nav__item"><a href="#" class="site-nav__link">About</a></li>
            <li class="site-nav__item"><a href="#" class="site-nav__link">Looooonger Title</a></li>
            <li class="site-nav__item"><a href="#" class="site-nav__link">Company</a></li>
            <li class="site-nav__item"><a href="#" class="site-nav__link">About</a></li>
            <li class="site-nav__item"><a href="#" class="site-nav__link">Login</a></li>
            <li class="site-nav__item"><a href="#" class="site-nav__link amp">Apply</a></li>
        </ul>
    </nav>
</header>

【问题讨论】:

你的问题是什么,我无法理解你的问题 我发布的 CodePen 大部分都有效。问题是没有添加 current-menu-item 类。在这种情况下,我需要隐藏这条线。然后,一旦将菜单项悬停在该行上就会淡入。然后,如果将鼠标悬停在其他菜单项上,它应该会滑动到其他菜单项。如果您离开菜单,它应该会再次淡出。 【参考方案1】:

就在关于列表项之前,添加具有anchor 标记且样式为display:noneli 标记可以解决此问题。

&lt;li class="site-nav__item current-menu-item"&gt;&lt;a href="#" style="display:none"&gt;&lt;/a&gt;&lt;/li&gt;

在不属于主菜单项的页面中使用这个额外的项目应该很有用。

【讨论】:

感谢您的回复!这似乎是一个解决方案,但我想我会进行一些挖掘,看看我是否可以让项目淡入而不是现在从左侧滑入。如果无法实现,这是一个不错的选择:) 希望你实现你想要的:0)【参考方案2】:

当没有current-menu-item 时,您将得到$(".current-menu-item a").position() 作为undefined。然后控制台报错

无法读取undefined 的“左”属性

因此,您必须检查current-menu-item 是否存在于width()css() 方法中,如下所示。

var $magicLine = $(".site-nav__line"),
    $currentMenu = $(".current-menu-item"); //added this line

$magicLine
    .width($currentMenu.length ? $currentMenu.width() : 0) //chnaged this line
    .css("left", $currentMenu.length ? $currentMenu.find("a").position().left : 0) //chnaged this line
    .data("origLeft", $magicLine.position().left)
    .data("origWidth", $magicLine.width());

快速移动鼠标问题更新: 要在没有current_menu_item 时淡入该行,您必须对hover 事件进行一些更改。对于快速鼠标移动问题,您可以使用setTimeoutclearTimeout

var hoverOut;

$(".site-nav__list li a").hover(function() 
  clearTimeout(hoverOut);

  $el = $(this);
  leftPos = $el.position().left;
  newWidth = $el.parent().width();

  if (!$magicLine.width()) 
    $magicLine.stop().hide().css(
      left: leftPos,
      width: newWidth
    ).fadeIn(400);
   else 
    $magicLine.stop().animate(
      opacity: 1,
      left: leftPos,
      width: newWidth
    );
  
, function() 
  hoverOut = setTimeout(function() 
    if (!$currentMenu.length) 
      $magicLine.fadeOut(400, function() 
        $magicLine.css(
          left: $magicLine.data("origLeft"),
          width: $magicLine.data("origWidth")
        );
      );
     else 
      $magicLine.stop().animate(
        left: $magicLine.data("origLeft"),
        width: $magicLine.data("origWidth")
      );
    
  , 400);
);

更新的笔链接: https://codepen.io/anon/pen/RBZwbZ

【讨论】:

看起来很棒!你能想出一种在没有current_menu_item 时淡入/淡出线路而不是从左侧滑入的方法吗?当您将鼠标悬停在其他项目上时,它仍然会滑动,但我认为如果它最初消失会很好?再次感谢! 谢谢你,我现在正在使用手机,但当我回到电脑上时我会检查一下!当您从导航中移除鼠标时,它是否也会淡出?可能没那么重要,但不确定我是否提到过 我想差不多了!我能看到的唯一问题是,如果您将鼠标快速移动到导航项目,它似乎没有注册,并且该行再次淡出。你会遇到这种情况吗? 查看我的更新答案。希望它能解决你的问题。 @user1406440 这看起来真的很好用!!移除鼠标时的延迟是否只是为了在鼠标移动过快等情况下不会淡出?只是给它一点时间以防出现故障?我喜欢它,就好像您在移到另一个不会损坏的项目之前先移开鼠标一秒钟。我可能会减少一点延迟,但我想不会太低,因为它的存在是有原因的?【参考方案3】:

当您没有.current-menu-item 时,$(".current-menu-item").width()$(".current-menu-item a").position().left 将返回 undefined 以使其崩溃。这里我对你的代码做了一点改动。

$(".site-nav__list li a").hover(function() 
        $el = $(this);
        leftPos = $el.position().left;
        newWidth = $el.parent().width();
        $magicLine.stop().animate(
            left: leftPos,
            width: newWidth
        );
    , function() 
        $magicLine.stop().animate(
            left: $magicLine.data("origLeft"),
            width: $magicLine.data("origWidth")
        );    
    );

$(".site-nav__list li a").hover(function() 
    $el = $(this);
    leftPos = $el.position().left;
    newWidth = $el.parent().width();
    if ($magicLine.width() >0) 
      $magicLine.stop().animate(
        left: leftPos,
        width: newWidth
      );
     else 
      $magicLine.width(newWidth).css("left", leftPos).fadeIn(3000);
    
, function() 
    $magicLine.stop().animate(
        left: $magicLine.data("origLeft"),
        width: $magicLine.data("origWidth")
    );    
);

还有

$magicLine.stop().animate(
    left: $magicLine.data("origLeft"),
    width: $magicLine.data("origWidth")
);

if ($currentMenu.length) 
       $magicLine.stop().animate(
            left: $magicLine.data("origLeft"),
            width: $magicLine.data("origWidth")
        );
        else 
        $magicLine.fadeOut('slow'); 
       

$(function()
	var $el, leftPos, newWidth,
        $mainNav = $(".site-nav__list");
    
    $mainNav.append("<div class='site-nav__line'></div>");
    var $magicLine = $(".site-nav__line"),
        $currentMenu = $(".current-menu-item");
  
    $magicLine
        .width($currentMenu.length ? $currentMenu.width() : 0)
        .css("left", $currentMenu.length ? $currentMenu.find("a").position().left : 0)
        .data("origLeft", $magicLine.position().left)
        .data("origWidth", $magicLine.width());

 $(".site-nav__list li a").hover(function() 
        $el = $(this);
        leftPos = $el.position().left;
        newWidth = $el.parent().width();
        if ($magicLine.width() >0) 
          $magicLine.show().stop().animate(
            left: leftPos,
            width: newWidth
          );
         else 
          $magicLine.width(newWidth).css("left", leftPos).fadeIn(3000);
        
    , function() 
   if ($currentMenu.length) 
       $magicLine.stop().animate(
            left: $magicLine.data("origLeft"),
            width: $magicLine.data("origWidth")
        );
        else 
        $magicLine.fadeOut('slow'); 
       
        
            
    );
);
/* MIXIN */

@mixin clearfix() 
	
	&:before,
	&:after 
		content: "";
		display: table;
	
	
	&:after 
		clear: both;
	


/* Body */

body 
  background: #f9f9f9;
  margin: 0;
  padding: 5px 0 0;


/* Header */

.page-head 
	background: white;
  border-top: 2px solid #ddd;
	box-sizing: border-box;
  @include clearfix;
	padding: 0 30px;
	position: relative;
	width: 100%;


.page-head__logo 
	background-image: none;
	float: left;
	padding: 0;
	text-shadow: none;
	width: 200px;


/* Nav */

.site-nav 
	display: block;
  float: right;
	text-align: center;
  width: auto;


.site-nav__list 
  list-style: none;
	margin: 0;
	padding: 0;
  position: relative;
  top: auto;
  left: auto;
  width: auto;


.site-nav__list li 
	background: none;
  display: inline-block;
	margin: 0;
	padding-left: 0;
	text-transform: uppercase;
	
	&.current-menu-item 


.site-nav__list a 
	box-sizing: border-box;
	display: block;
	font-weight: 900;
	padding: 30px 15px;
	transition: color .15s;
	text-shadow: none;
  
  &:hover 
    color: red;
  


/* Underline */

.site-nav__line 
  background: red;
  content: "";
  display: block;
  height: 2px;
  position: absolute;
  top: -2px;
  left: 0;
  width: 100%;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<body>
  <header class="page-head">

    <a href="#" class="page-head__logo">Logo Here </a>

    <nav class="site-nav">
      <ul class="site-nav__list">
        <li class="site-nav__item "><a href="#" class="site-nav__link">Home</a></li>
        <li class="site-nav__item"><a href="#" class="site-nav__link">About</a></li>
        <li class="site-nav__item"><a href="#" class="site-nav__link">Looooonger Title</a></li>
        <li class="site-nav__item"><a href="#" class="site-nav__link">Company</a></li>
        <li class="site-nav__item"><a href="#" class="site-nav__link">About</a></li>
        <li class="site-nav__item"><a href="#" class="site-nav__link">Login</a></li>
        <li class="site-nav__item"><a href="#" class="site-nav__link amp">Apply</a></li>
      </ul>
    </nav>

  </header>
</body>

【讨论】:

感谢您的解释,这是有道理的。该示例的唯一问题是我仍然希望线条从链接滑动到链接,效果很好。只是当没有current_menu_item 并且您将鼠标悬停在最初应该淡入的链接上时。然后它应该像它已经做的那样滑动到其他项目。这有意义吗?不然很抱歉! @user1406440 我已经在上面更新了希望这是你要找的。​​span> 嘿,我认为这很接近!我认为如果当您将鼠标从导航链接移开而不是滑到左侧时线条淡出会很好,您怎么看?再次感谢! @user1406440 好的,给我一些时间我会更新我的答案 @user1406440 答案已更新,希望这是您要找的。 :)

以上是关于悬停时的导航滑动线 - 当没有项目是“当前”或“选定”时的主要内容,如果未能解决你的问题,请参考以下文章

鼠标移动时的悬停延迟

悬停时,将导航图标从当前页面项目移动到悬停

如何使用 jQuery 停止/暂停鼠标悬停在导航上的滑动?

Android仿IOS ViewPager滑动进度条

悬停或单击时的 Jquery 下拉菜单

当目的地的必需参数来自可选状态变量时的 NavigationLink