【问题标题】:Detect When Mouse Enters Specific Area of Document (Not a Div Element)检测鼠标何时进入文档的特定区域(不是 Div 元素)
【发布时间】:2016-12-22 00:29:08
【问题描述】:

我试图弄清楚当您的鼠标进入文档底部时Medium 是如何让他们的底部操作/菜单栏向上滑动的。将鼠标移到不可见的 div 上不会触发上滑效果(它通过变换 translateY 上下滑动)。

此外,菜单栏的高度只有 44 像素,但它的 is-visible 类在你的鼠标靠近它之前就被触发了——但是通过什么?使用 Inspect Element 时,我看不到任何可能触发它的隐藏 div..

我已经搜索了无数种方法,例如“当鼠标进入文档的特定部分时显示元素”但所有搜索结果都涉及鼠标进入或移动到 div 元素时,这不是我正在寻找的解决方案。

显然,您可以通过像我在这里所做的那样将上滑菜单放在隐藏容器中来解决这个问题,然后您会得到想要的结果:

(function() {

  var actionBar = document.querySelector('.action-bar');
  var actionBarWrapper = document.querySelector('.action-bar-detection');

  function showDiv() {
    actionBar.classList.add('js-is-visible')
  }

  function hideDiv() {
    actionBar.classList.remove('js-is-visible')
  }

  actionBarWrapper.onmouseover = showDiv;
  actionBarWrapper.onmouseout = hideDiv;

})();
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
  line-height: 1.5;
}

body {
  height: 100%;
}

.wrapper {
  width: 90%;
  max-width: 600px;
  margin: 5% auto;
}

.action-bar {
  position: absolute;
  left: 0;
  bottom: 0;
  border: 1px solid #252321;
  background: #fff;
  padding: 16px;
  width: 100%;
  min-height: 50px;
  opacity: 0;
  transform: translateY(100%);
  transition: all .5s;
  z-index: 99;
}

.action-bar-detection {
  height: 150px;
  width: 100%;
  opacity: 1;
  position: fixed;
  bottom: 0;
  left: 0;
  z-index: 1;
}

.js-is-visible {
  opacity: 1;
  transform: translateY(0%);
}
<html>

<head>
  <meta charset="UTF-8" />
  <title>Document</title>
</head>

<body>

  <div class="wrapper">

    <p>When mouse enters the hidden action bar element, slides up.</p>
    <p>But it's only happening because the action-bar is inside an invisible detection layer class (action-bar-detection) with a height of 150px.</p>

  </div>
  <div class="action-bar-detection">
    <div class="action-bar">

      Bottom Menu
    </div>
  </div>

</body>

</html>

但是,这似乎不是 Medium 所做的,如果可以在不添加更多 HTML 和 CSS 的情况下做到这一点,我想学习如何! :-)

我认为我没有正确地表达问题,因为我找不到任何解决方案,即使是远程关闭(我已经搜索了很多)。

有什么建议吗?我应该读什么? :-)

【问题讨论】:

    标签: javascript


    【解决方案1】:

    获取视口高度,跟踪onmousemove,并将鼠标事件中的clientY与视口高度进行比较:

    (function() {
    
      var actionBar = document.querySelector('.action-bar');
      var viewHeight = window.innerHeight - 150;
    
      function toggleDiv(e) {
        if (e.clientY >= viewHeight) {
          actionBar.classList.add('js-is-visible');
        } else {
          actionBar.classList.remove('js-is-visible');
        }
      }
    
      window.onmousemove = toggleDiv;
    
    })();
    * {
      margin: 0;
      padding: 0;
      box-sizing: border-box;
      line-height: 1.5;
    }
    body {
      height: 100%;
    }
    .wrapper {
      width: 90%;
      max-width: 600px;
      margin: 5% auto;
    }
    .action-bar {
      position: absolute;
      left: 0;
      bottom: 0;
      border: 1px solid #252321;
      background: #fff;
      padding: 16px;
      width: 100%;
      min-height: 50px;
      opacity: 0;
      transform: translateY(100%);
      transition: all .5s;
      z-index: 99;
    }
    .action-bar-detection {
      height: 150px;
      width: 100%;
      opacity: 1;
      position: fixed;
      bottom: 0;
      left: 0;
      z-index: 1;
    }
    .js-is-visible {
      opacity: 1;
      transform: translateY(0%);
    }
    <div class="wrapper">
      <p>When mouse comes within 150px of the bottom part of the screen, the bar slides up.</p>
      <p>When the mouse leaves this defined area of the screen, the bar slides down.</p>
    </div>
    <div class="action-bar-detection">
      <div class="action-bar">
        Bottom Menu
      </div>
    </div>

    【讨论】:

      【解决方案2】:

      您可以通过收听文档上的mousemove 事件来做到这一点,您需要投入精力来提高性能,因为它会被频繁触发。管理此类事件的最常见方法是通过throttling

      一旦你进入 mousemove 事件,你将需要获取光标的 Y 坐标并将其与窗口的高度进行比较,如果它在阈值内,那么你可以显示你的面板,一旦它移出你可以继续隐藏它。

      这是一个显示基本实现的示例jsFiddle

      // Using underscore for the throttle function though you can implement your own if you wish
      document.addEventListener('mousemove', _.throttle(mouseMoveEventAction, 200));
      
      function mouseMoveEventAction(e) {
      	doPanelStuff(isInsideThreshold(e.clientY));
      }
      
      function doPanelStuff(isActive) {
      	var panelElement = document.querySelector('.panel');
        if (isActive) {
        	panelElement.style.background = 'red';
        } else {
        	panelElement.style.removeProperty('background');
        }
      }
      
      function isInsideThreshold(cursorY) {
      	var threshold = 200;
      	var clientHeight = document.documentElement.clientHeight;
        return cursorY > (clientHeight - threshold);
      }
      html, body {
        height: 100%;
      }
      
      .container, .content {
        height: 100%;
        width: 100%;
      }
      
      .panel {
        height: 50px;
        position: absolute;
        bottom: 0;
        width: 100%;
        background: green;
      }
      <script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>
      <div class="container">
        <div class="content"></div>
        <div class="panel"></div>
      </div>

      【讨论】:

      • 谢谢。我什至没有考虑过节流问题!
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-30
      • 1970-01-01
      • 1970-01-01
      • 2020-06-27
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多