javascript – 强制CSS的解决方法:转换后悬停更新(打开菜单)

前端之家收集整理的这篇文章主要介绍了javascript – 强制CSS的解决方法:转换后悬停更新(打开菜单)前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
解决这个问题已经有几个问题了.我包括我有两个原因:

>它提出了一种可能的替代方案
>演示代码可能对想要模拟菜单的其他人有用

在CSS转换之后,用户必须先移动鼠标,然后现在鼠标下的元素将注意到它处于:悬停状态.我创建了一个菜单功能,可以打开以显示不同的选项.打开过渡结束时鼠标下的选项与过渡开始时鼠标下的选项不同.因此,我必须找到一种解决方法.

您可以在下面找到jsFiddle here和演示源.寻找WORKAROUND(在三个地方)看看我做了什么.

要查看问题,请将鼠标移到菜单上,然后将其保留在原位,而不移动它.浏览器认为的列表项是:hover将显示为蓝色.我的解决方法使用li.ignoreHover类否决了li:hover规则.为了使变通方法不可见,我可以简单地使用标准背景颜色.相反,我使用蓝色使问题可见.

我的问题:我注意到按下其中一个修饰键(Caps,Caps lock,Ctrl,Option / Alt,⌘on Mac,…)也会强制:hover状态更新.有没有办法将这样的事件发送到#menu元素?

(我这样做的尝试并没有成功,所以我更倾向于给你我的工作解决方案而不是一个可能无效的解决方法).

<!DOCTYPE html>
<html>
<head>
 <style>
#menu {
  position: relative;
  background: #ccc;
  display: inline-block;
}
#wrapper {
  margin: 5px;
}
#logo {
  width: 150px;
  height: 50px;
  border: 1px solid #000;
  margin: 0px auto;
  z-index: 10;
}
nav {
  width: 100%;
  overflow: hidden;
  text-align:center;
  height: 2em;
}
ul {
  position: relative;
  display:inline-block;
  margin: 0 auto;
  padding: 0;
  list-style-type: none;
  text-align:left;
}
li {
  display: block;
  margin: 0;
  padding:0.25em 0;
  line-height: 1.5em;
}
ul.animated,nav {
  transition: all 500ms linear 1s;
}
#menu.hover ul,#menu.hover nav {
  transition-delay: 0s;
}
li:hover,li.hover {
  background-color: #999;
}
li.ignoreHover {
  background-color: #ccf; /* a touch of blue,so you can see it */
}
.selected {
  color: #fff;
}
 </style>
  <script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script> 
</head>
<body>
<div id="menu">
  <div id="wrapper">
    <div id="logo"></div>
  </div>
  <nav>
    <ul>
      <li>Note one</li>
      <li>Note two</li>
      <li>Note three</li>
      <li>Not four much longer</li>
      <li>Note five</li>
      <li>Note six</li>
    </ul>
  </nav>
</div>

<script>
var test = {}
;(function createMenu() {
    var item = 3;
    var minPadding = 5;
    var hover = "hover" // class

    var $li = $("li");
    var $ul = $("ul");
    var $menu = $("#menu");
    var $nav = $("nav");

    var itemHeight = parseInt($li.outerHeight(),10);
    var itemCount = $ul.children().length;
    var menuWidth = $menu.outerWidth(true);
    var padding = (menuWidth - $ul.width()) / 2;

    var transitionDone = false;
    var mouSEOver = false;
    var top;

    // Pad the list items to fill the width of the menu
    if (padding < minPadding) {
        // Widen the menu to allow for the minimum padding
        menuWidth += (minPadding - padding) * 2;
        $menu.width(menuWidth);
        padding = minPadding;
    }

    $li.css({
        paddingLeft: padding,paddingRight: padding
    });

    // Scroll to the current selected item
    selectItem(true);

    function selectItem(scroll) {
        $ul.children().removeClass("selected");
        $ul.children().eq(item).addClass("selected");

        if (scroll) {
            top = -(itemHeight * item);
            $ul.css({
                top: top
            });
        }
    }

    // Wait until the initial settings are applied 
    // before animating the transitions
    setTimeout(function () {
        $ul.addClass("animated");
    },1);

    // Handle interaction with the menu
    $menu.on("mouSEOver",openMenu);
    $menu.on("mouseleave",closeMenu);
    $menu.on("transitionend",menuIsOpen);
    $ul.on("click",treatClickOnItem);

    // <WORKAROUND...
    var x
    var y
    // ... WORKAROUND>


  function openMenu(event) {

        if (mouSEOver) {
            // This method may be called multiple times as the menu is
            // transitioning to its open state
            return
        }

    // <WORKAROUND...
    $menu.on("mousemove",function updateXY(event) {
            x = event.pageX
            y = event.pageY
    })
    // ... WORKAROUND>

        $menu.addClass(hover);
        transitionDone = false;
        mouSEOver = true;

        $nav.css({
            height: (itemHeight * itemCount)
        });
        $ul.css({
            top: 0
        });
    }

    function menuIsOpen() {
        transitionDone = true;

      // <WORKAROUND...   
    var $hover = $("li:hover").addClass("ignoreHover")
    var $item = $(document.elementFromPoint(x,y))
    if (mouSEOver) {
      $item.addClass(hover)
    }
    $menu.on("mousemove",function () {
      $item.removeClass(hover)
      $hover.removeClass("ignoreHover")
      $menu.off("mousemove")
    })
        //... WORKAROUND>

        if (!mouSEOver) {
            closeMenu()
        }
    }

    function closeMenu() {
        mouSEOver = false;
        if (transitionDone) {
            $menu.removeClass(hover)

            $nav.css({
                height: itemHeight
            });
            $ul.css({
                top: top
            });
        }
  }

    function treatClickOnItem(event) {
        item = $(event.target).index();
        top = -(itemHeight * item);
        selectItem();
        // DO MORE STUFF WITH THE SELECTION
    }
})()
</script>
</body>
</html>

解决方法

jsBin demo

Seems like it’s almost impossible获取:元素的悬停状态,同时它是动画.

删除:将鼠标悬停在CSS和
创建一个具有所需样式的类.hover.使用jQuery切换.hover:

$links.hover(function(){
  $(this).toggleClass("hover");
});

现在回到你的问题:

为了在菜单打开后突出显示正确的元素
我们需要始终知道鼠标Y的位置:

var mouseY = 0; // Needed to know the mouse position when menu is opening
$(document).on("mousemove",function( e ){
    mouseY = e.clientY; // Update the Y value
});

现在,在折叠的菜单悬停上,使用jQuery为菜单设置动画,
在animate步骤内部回调在每个帧上获取每个链接位置,.filter()通过定位匹配鼠标位置的那个.
最后将.hover应用于那个:

function openMenu() {
  $navUl.stop().animate({top: 0});
  $nav.stop().animate({height: linkH*nLinks},{
    duration: 600,step: function( menuHeight ){
        // keeps removing and adding class during the animation time.
        // (it's an overkill but no other solution to that issue so far)
        $links.removeClass("hover").filter(function(i,e){
          var t = e.getBoundingClientRect().top;
          return mouseY > t  &&  mouseY < t+linkH;
        }).addClass("hover"); // only to the link returned by `.filter()` condition
    }
  });
}

!重要提示:上述过滤将与您拥有的许多项目一样昂贵,因为它会在每个动画帧中尝试获取位置.如果你发现缓慢 – 改善上述.

回顾一下在每一帧检查鼠标clientX / Y坐标是否在元素的element.getBoundingClientRect()坐标/值内

猜你在找的JavaScript相关文章