简体   繁体   English

如何在div的位置添加事件监听器?

[英]How do I add an event listener on position of a div?

I want a css property of a div to change when a sibling div hits the top of the viewport. 我希望当同级div到达视口顶部时,更改div的css属性。

Specifically I would like the "second-subdiv" to have overflow: scroll only when the "first-subdiv" hits the top of the viewport. 具体来说,我希望“ second-subdiv” overflow: scroll仅在“ first-subdiv”到达视口顶部时overflow: scroll

Basically I would like to set overflow: hidden on the "second-subdiv" and then write a couple of lines of js in which I would say: 基本上,我想设置overflow: hidden在“ second-subdiv”上,然后写几行js,其中我会说:

add.EventListener(when-first-subdiv-is-on-top, change the overflow property)

<div class="first-div">
  <h1>Title</h1>
</div>

<div class= "second-div">
  <div class="first subdiv">
    <h1>You are Beautiful</h1>
  </div>
  <div class="second subdiv">
    <h2>Something Good</h2>
    <h2>Something Good</h2>
    <h2>Something Good</h2>
    <h2>Something Good</h2>
    <h2>Something Good</h2>
    <h2>Something Good</h2>
    <h2>Something Good</h2>
    <h2>Something Good</h2>
    <h2>Something Good</h2>
    <h2>Something Good</h2>
    <h2>Something Good</h2>
    <h2>Something Good</h2>
    <h2>Something Good</h2>
    <h2>Something Good</h2>
    <h2>Something Good</h2>
    <h2>Something Good</h2>
    <h2>Something Good</h2>
    <h2>Something Good</h2>
    <h2>Something Good</h2>
    <h2>Something Good</h2>
  </div>
</div>
html, body {
  margin: 0;
  padding: 0;
}
.first-div {
  margin: 0;
  width: 100%;
  height: 80vh;
  background-color: red;
  display: flex;
  justify-content: center;
  align-items: center;
  h1 {
    color: white;
  }
}
.second-div {
  display: flex;
  justify-content: space-around;
}
.subdiv {
  width: 50%;
  height: 100vh;
  text-align: center;
  overflow: scroll;
}
.first.subdiv {
  background-color: magenta;
}
.second.subdiv {

}

Any help with that? 有什么帮助吗?

Thanks, 谢谢,

Matteo 马特奥

Let's first define a function that implements the required styling logic. 首先定义一个实现所需样式逻辑的函数。

const EPSILON = 0.5;

function setOverflow () {
  var firstDiv = document.querySelector('.first.subdiv');
  var secondDiv = document.querySelector('.second.subdiv');
  var rect = firstDiv.getBoundingClientRect();
  if (Math.abs(rect.top) < EPSILON) {
    secondDiv.style.overflow = 'scroll';
  }
  else {
    secondDiv.style.overflow = 'hidden';
  }
}

The function setOverflow will read the position of the .first.subdiv , using get​Bounding​Client​Rect , and check if its top -coordinate is close enough to zero (ie, the window's top border) and set the overflow style property accordingly. 该功能setOverflow将读取的位置.first.subdiv ,使用得到边界客户端矩形 ,并检查它的top -协调足以为零(即窗口的上边框)关闭并设置相应的溢出样式属性。 As the top -coordinate will not usually be exactly 0 , the tolerance for close enough to 0 is defined to be between -0.5 and 0.5, by the EPSILON variable. 由于top坐标通常不会精确地为0 ,因此通过EPSILON变量将足够接近 0的公差定义为-0.5至0.5。

This function has to run whenever the position of the .first.subdiv element changes, such that the overflow property can be recalculated. 每当.first.subdiv元素的位置更改时,该函数都必须运行,以便可以重新计算溢出属性。 You will need at least these events: load , resize , scroll , but you may need more depending on your final result. 您至少需要以下事件: loadresizescroll ,但是根据最终结果,可能还需要更多事件。 For example, if images are added dynamically, the position of the .first.subdiv may change without any of the above events triggering. 例如,如果动态添加图像,则.first.subdiv的位置可能会更改,而不会触发任何上述事件。 You may want to look into the suggestion of Dale Harris and opt for the Intersection Observer API . 您可能需要研究Dale Harris的建议,并选择Intersection Observer API

To avoid recalculating the overflow too many times, wrap the function call in a window.requestAnimationFrame . 为避免过多地重新计算溢出,请将函数调用包装在window.requestAnimationFrame中

function maybeSetOverflow () {
  if (!setOverflow.isBusy) {
    setOverflow.isBusy = true;
    window.requestAnimationFrame(() => {setOverflow.isBusy = false; setOverflow()});
  }
}

window.addEventListener('scroll', maybeSetOverflow);
window.addEventListener('resize', maybeSetOverflow);
window.addEventListener('load'  , maybeSetOverflow);

The function maybeSetOverflow will ignore duplicate calls to setOverflow, if it has already been called, but not executed in the animation frame. 该功能maybeSetOverflow会忽略到setOverflow重复调用,如果它已经被调用,但在动画帧不执行。

Just wrap both of these code parts in a <script> and put it at the bottom of your <body> . 只需将这两个代码部分包装在<script> ,并将其放在<body>的底部。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM