【问题标题】:Show element when in viewport on scroll在滚动视口中显示元素
【发布时间】:2023-04-11 01:30:02
【问题描述】:

当元素在视口中时,我一直试图在滚动上显示它,如果没有,则再次隐藏它。但无论我怎么尝试,我都无法成功。

这是我目前所拥有的,但该函数只运行一次,当页面加载而不是滚动时,所以它不会更新值。

$(window).scroll(function() {
    var top_of_element = $("#cont_quote blockquote").offset().top;
    var bottom_of_element = $("#cont_quote blockquote").offset().top + $("#cont_quote blockquote").outerHeight();
    var bottom_of_screen = $(window).scrollTop() + window.innerHeight;
    var top_of_screen = $(window).scrollTop();

    if((bottom_of_screen > top_of_element) && (top_of_screen < bottom_of_element)){
       $('#cont_quote blockquote').animate({'opacity':'1'},1000);
    }
    else {
       $('#cont_quote blockquote').animate({'opacity':'0'},1000);
    }
});



<section id="cont_quote">
    <article class="cont_q">
        <blockquote>Lorem ipsum</blockquote>
    </article>
</section>

【问题讨论】:

    标签: javascript jquery html scroll viewport


    【解决方案1】:

    在纯 javascript 中,你可以做这样的事情,它使用的资源比完整的 jQuery 方法少得多:

    function inViewport( element ){
      
      // Get the elements position relative to the viewport
    
      var bb = element.getBoundingClientRect();
      
      // Check if the element is outside the viewport
      // Then invert the returned value because you want to know the opposite
    
      return !(bb.top > innerHeight || bb.bottom < 0);
      
    }
    
    var myElement = document.querySelector( 'div' );
    
    // Listen for the scroll event
    
    document.addEventListener( 'scroll', event => {
     
      // Check the viewport status
    
      if( inViewport( myElement ) ){
        
        myElement.style.background = 'red';
        
      } else {
        
        myElement.style.background = '';
        
      }
      
    })
    body {
      
      height: 400vh;
      
    }
    
    div {
      
      width: 50vw;
      height: 50vh;
      position: absolute;
      top: 125vh;
      left: 25vw;
      transition: background 4s;
      border: 1px solid red;
      
    }
    <p>Scroll Down</p>
    <div></div>

    这是一个带有不透明度变化的 sn-p:

    function inViewport( element ){
      
      // Get the elements position relative to the viewport
    
      var bb = element.getBoundingClientRect();
      
      // Check if the element is outside the viewport
      // Then invert the returned value because you want to know the opposite
    
      return !(bb.top > innerHeight || bb.bottom < 0);
      
    }
    
    var myElement = document.querySelector( 'div' );
    
    // Listen for the scroll event
    
    document.addEventListener( 'scroll', event => {
     
      // Check the viewport status
    
      if( inViewport( myElement ) ){
        
        myElement.style.opacity = 1;
        
      } else {
        
        myElement.style.opacity = '';
        
      }
      
    })
    body {
      
      height: 400vh;
      
    }
    
    div {
      
      width: 50vw;
      height: 50vh;
      position: absolute;
      top: 125vh;
      left: 25vw;
      transition: opacity 1s;
      opacity: .2;
      background: blue;
      
    }
    <p>Scroll Down</p>
    <div></div>

    这里是一个 sn-p,向您展示如何定义它在视口中触发的位置,我只是将 innerHeight0 值更改为 object,您可以在其中定义从顶部开始的像素数量应该是和底部的像素数量。不要忘记还为resize 添加一个事件侦听器,因为如果您的视口发生变化,这些基于像素的值会发生变化,因此您的myViewport 对象需要相应地更新:

    function inViewport( element, viewport = { top: 0, bottom: innerHeight } ){
      
      // Get the elements position relative to the viewport
    
      var bb = element.getBoundingClientRect();
      
      // Check if the element is outside the viewport
      // Then invert the returned value because you want to know the opposite
    
      return !(bb.top > viewport.bottom || bb.bottom < viewport.top);
      
    }
    
    var myViewport = { top: innerHeight * .4, bottom: innerHeight * .6 };
    var myElement = document.querySelector( 'div' );
    
    // Listen for the scroll event
    
    document.addEventListener( 'scroll', event => {
     
      // Check the viewport status
    
      if( inViewport( myElement, myViewport ) ){
        
        myElement.style.opacity = 1;
        
      } else {
        
        myElement.style.opacity = '';
        
      }
      
    })
    
    window.addEventListener( 'resize', event => {
     
      // Update your viewport values
    
      myViewport.top = innerHeight * .4;
      myViewport.bottom = innerHeight * .6;
      
    })
    body {
      
      height: 400vh;
      
    }
    
    div {
      
      width: 50vw;
      height: 50vh;
      position: absolute;
      top: 125vh;
      left: 25vw;
      transition: opacity 1s;
      opacity: .2;
      background: blue;
      
    }
    <p>Scroll Down</p>
    <div></div>

    【讨论】:

    • @marco 我的错,我更改了变量名称以使其更清晰,但没有在滚动代码中的变量中更改它。对其进行了修改并更改了可视化效果,当在视口中使用过渡时,背景现在将被填充,结果很清楚。
    • @marco 是的,这可行,我只是选择了背景,因为我还可以显示元素出现位置的边框。只需确保元素的原始不透明度为0 否则您将看不到更改(如果您在离开可滚动区域后将元素不透明度设置为 0,那么您只会在下次进入视图时看到更改)
    • @marco 我添加了一个不透明度从 0.2 更改为 1 的 sn-p(这样您就不会在滚动时错过该元素,但可以随意将原始不透明度更改为 0在 CSS 中)
    • 谢谢!它真的很好用。我还想做一件事。不要在元素出现在视口中时显示它,而是在它位于视口的中间时显示它,就像仅在它位于视口高度的 40% 时一样。我试过return !((bb.top + 300) &gt; innerHeight || (bb.bottom - 100) &lt; 0);,但我更喜欢有一个百分比的响应
    • @marco 我添加了另一个具有该功能的 sn-p。只需以像素为单位定义视口的顶部和底部(我根据视口的高度计算它们)并检查这些值。
    【解决方案2】:

    尝试使用:

    $(window).on('scroll mousewheel', function() {
    

    并在你的功能周围加上:

    $(document).ready(function(){
    });
    

    【讨论】:

    • @Marco 问题也可能出在你的 CSS 中。像 html/body 高度设置为 100% 或溢出设置。否则你也可以尝试使用 $('#cont_quote').on('scroll', function(){
    【解决方案3】:

    我试图仅通过您的代码来解决您的问题。它现在对我来说工作正常。请试试这个,让我知道。也打开你的浏览器控制台看看有没有js错误。

    $(window).scroll(function() {
      var top_of_element = $("#cont_quote blockquote").offset().top;
      var bottom_of_element = $("#cont_quote blockquote").offset().top + $("#cont_quote blockquote").outerHeight();
      var bottom_of_screen = $(window).scrollTop() + window.innerHeight;
      var top_of_screen = $(window).scrollTop();
    
      if((bottom_of_screen > top_of_element) && (top_of_screen < bottom_of_element)){
        $('#cont_quote blockquote').fadeIn(1000);
        console.log('if cond');
      } else {      
        $('#cont_quote blockquote').fadeOut(1000);
        console.log('else cond');
      }
    });
    

    【讨论】:

    • 很好,但是向下滚动然后向上滚动时就不行了
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-08
    • 1970-01-01
    • 2015-06-20
    • 2019-01-12
    • 1970-01-01
    相关资源
    最近更新 更多