在向下滚动时淡入,在向上滚动时淡出 - 基于窗口中的元素位置

时间:2014-11-01 23:32:27

标签: javascript jquery scroll fade

当我们在窗口中完全可见时,我试图让一系列元素在向下滚动时淡入。如果我继续向下滚动,我不希望它们淡出,但如果我向上滚动,我确实希望它们淡出。

这是我发现的最接近的jsfiddle。 http://jsfiddle.net/tcloninger/e5qaD/

$(document).ready(function() {

/* Every time the window is scrolled ... */
$(window).scroll( function(){

    /* Check the location of each desired element */
    $('.hideme').each( function(i){

        var bottom_of_object = $(this).position().top + $(this).outerHeight();
        var bottom_of_window = $(window).scrollTop() + $(window).height();

        /* If the object is completely visible in the window, fade it it */
        if( bottom_of_window > bottom_of_object ){

            $(this).animate({'opacity':'1'},500);

        }    
    }); 
}); 
});

它完全按照我想要的向下滚动,但如果我向上滚动它们,我也希望元素淡出。

我试了这个没有运气。

            if( bottom_of_window > bottom_of_object ){

                $(this).animate({'opacity':'1'},500);  

            } else {

               $(this).animate({'opacity':'0'},500); }

非常感谢您花时间看这个。

4 个答案:

答案 0 :(得分:38)

你的尝试不起作用的原因是因为两个动画(淡入和淡出)相互作用。

在对象变得可见之前,它仍然是不可见的,因此淡出的动画将会运行。然后,当相同的对象变得可见时,一小段时间后,淡入动画将尝试运行,但淡出仍然在运行。所以他们会相互对抗,你什么也看不见。

最终,对象将变得可见(大部分时间),但需要一段时间。如果您使用滚动条按钮上的箭头按钮向下滚动,则动画会有效,因为您可以使用更大的增量滚动,从而创建更少的滚动事件。


足够的解释,解决方案(JS,CSS,HTML):



$(window).on("load",function() {
  $(window).scroll(function() {
    var windowBottom = $(this).scrollTop() + $(this).innerHeight();
    $(".fade").each(function() {
      /* Check the location of each desired element */
      var objectBottom = $(this).offset().top + $(this).outerHeight();
      
      /* If the element is completely within bounds of the window, fade it in */
      if (objectBottom < windowBottom) { //object comes into view (scrolling down)
        if ($(this).css("opacity")==0) {$(this).fadeTo(500,1);}
      } else { //object goes out of view (scrolling up)
        if ($(this).css("opacity")==1) {$(this).fadeTo(500,0);}
      }
    });
  }).scroll(); //invoke scroll-handler on page-load
});
&#13;
.fade {
  margin: 50px;
  padding: 50px;
  background-color: lightgreen;
  opacity: 1;
}
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>

<div>
  <div class="fade">Fade In 01</div>
  <div class="fade">Fade In 02</div>
  <div class="fade">Fade In 03</div>
  <div class="fade">Fade In 04</div>
  <div class="fade">Fade In 05</div>
  <div class="fade">Fade In 06</div>
  <div class="fade">Fade In 07</div>
  <div class="fade">Fade In 08</div>
  <div class="fade">Fade In 09</div>
  <div class="fade">Fade In 10</div>
</div>
&#13;
&#13;
&#13; (小提琴:http://jsfiddle.net/eLwex993/2/

  • 我将fade-codeline包装在if子句中:if ($(this).css("opacity")==0) {...}。这样可确保在opacity0时对象才会淡入。淡出一样。这可以防止淡入和淡出相互作用,因为现在只有两个中的一个同时在一个物体上运行。
  • 我将.animate()更改为.fadeTo()。它是jQuery不透明的专用功能,写入时间要短得多,而且可能比动画更轻。
  • 我将.position()更改为.offset()。这总是相对于身体计算,而位置是相对于父亲。对于你的情况,我认为偏移是要走的路。
  • 我将$(window).height()更改为$(window).innerHeight()。根据我的经验,后者更可靠。
  • 在滚动处理程序之后,我使用$(window).scroll();在页面加载时调用该处理程序一次。现在,您可以在页面上为.fade类提供所有需要的对象,并且在页面加载时应该不可见的对象将立即淡出。
  • 我从HTML和CSS中删除了#container,因为(至少对于这个答案)它是不必要的。 (我想也许你需要height:2000px,因为你使用的是.position()而不是.offset(),否则我就不知道了。当然不要把它留在你的代码中。)< / LI>

更新

如果您想要01以外的不透明度值,请使用以下代码:

&#13;
&#13;
$(window).on("load",function() {
  function fade(pageLoad) {
    var windowBottom = $(window).scrollTop() + $(window).innerHeight();
    var min = 0.3;
    var max = 0.7;
    var threshold = 0.01;
    
    $(".fade").each(function() {
      /* Check the location of each desired element */
      var objectBottom = $(this).offset().top + $(this).outerHeight();
      
      /* If the element is completely within bounds of the window, fade it in */
      if (objectBottom < windowBottom) { //object comes into view (scrolling down)
        if ($(this).css("opacity")<=min+threshold || pageLoad) {$(this).fadeTo(500,max);}
      } else { //object goes out of view (scrolling up)
        if ($(this).css("opacity")>=max-threshold || pageLoad) {$(this).fadeTo(500,min);}
      }
    });
  } fade(true); //fade elements on page-load
  $(window).scroll(function(){fade(false);}); //fade elements on scroll
});
&#13;
.fade {
  margin: 50px;
  padding: 50px;
  background-color: lightgreen;
  opacity: 1;
}
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>

<div>
  <div class="fade">Fade In 01</div>
  <div class="fade">Fade In 02</div>
  <div class="fade">Fade In 03</div>
  <div class="fade">Fade In 04</div>
  <div class="fade">Fade In 05</div>
  <div class="fade">Fade In 06</div>
  <div class="fade">Fade In 07</div>
  <div class="fade">Fade In 08</div>
  <div class="fade">Fade In 09</div>
  <div class="fade">Fade In 10</div>
</div>
&#13;
&#13;
&#13; (小提琴:http://jsfiddle.net/eLwex993/3/

  • 我在if子句中添加了一个阈值,请参阅下面的说明
  • 我在函数开头为thresholdmin/max创建了变量。在函数的其余部分中,引用了这些变量。这样,如果您想再次更改值,则只需在一个地方进行更改。
  • 我还在if子句中添加了|| pageLoad。这是确保所有对象在页面加载时淡化到正确的不透明度所必需的。 pageLoad是一个布尔值,在调用fade()时作为参数发送 我必须将淡入淡出代码放在额外的function fade() {...}内,以便在调用scroll-handler时能够发送pageLoad布尔值。
    我没有看到任何其他方式来做这件事,如果有其他人这样做,请发表评论。

<强>解释
your fiddle中的代码无效的原因是因为实际不透明度值总是与您设置的值略有不同。因此,如果您将不透明度设置为0.3,则实际值(在本例中)为0.300000011920929。这只是你必须通过追踪和错误一路学习的小错误中的一个。这就是为什么这个if-clause无法工作的原因:if ($(this).css("opacity") == 0.3) {...}

我添加了一个阈值,以考虑到这一差异:== 0.3变为<= 0.31 (我已将阈值设置为0.01,当然,只要实际不透明度介于设定值和此阈值之间,就可以更改此阈值。)

现在,运营商已从==更改为<=>=


更新2:

如果您想根据可见百分比淡化元素,请使用以下代码:

&#13;
&#13;
$(window).on("load",function() {
  function fade(pageLoad) {
    var windowTop=$(window).scrollTop(), windowBottom=windowTop+$(window).innerHeight();
    var min=0.3, max=0.7, threshold=0.01;
    
    $(".fade").each(function() {
      /* Check the location of each desired element */
      var objectHeight=$(this).outerHeight(), objectTop=$(this).offset().top, objectBottom=$(this).offset().top+objectHeight;
      
      /* Fade element in/out based on its visible percentage */
      if (objectTop < windowTop) {
        if (objectBottom > windowTop) {$(this).fadeTo(0,min+((max-min)*((objectBottom-windowTop)/objectHeight)));}
        else if ($(this).css("opacity")>=min+threshold || pageLoad) {$(this).fadeTo(0,min);}
      } else if (objectBottom > windowBottom) {
        if (objectTop < windowBottom) {$(this).fadeTo(0,min+((max-min)*((windowBottom-objectTop)/objectHeight)));}
        else if ($(this).css("opacity")>=min+threshold || pageLoad) {$(this).fadeTo(0,min);}
      } else if ($(this).css("opacity")<=max-threshold || pageLoad) {$(this).fadeTo(0,max);}
    });
  } fade(true); //fade elements on page-load
  $(window).scroll(function(){fade(false);}); //fade elements on scroll
});
&#13;
.fade {
  margin: 50px;
  padding: 50px;
  background-color: lightgreen;
  opacity: 1;
}
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>

<div>
  <div class="fade">Fade In 01</div>
  <div class="fade">Fade In 02</div>
  <div class="fade">Fade In 03</div>
  <div class="fade">Fade In 04</div>
  <div class="fade">Fade In 05</div>
  <div class="fade">Fade In 06</div>
  <div class="fade">Fade In 07</div>
  <div class="fade">Fade In 08</div>
  <div class="fade">Fade In 09</div>
  <div class="fade">Fade In 10</div>
</div>
&#13;
&#13;
&#13; (小提琴:http://jsfiddle.net/eLwex993/5/

答案 1 :(得分:3)

我稍稍调整了你的代码并使其更加健壮。就渐进增强而言,在JavaScript中拥有所有淡入逻辑可能会更好。在myfunksyde的示例中,任何没有JavaScript的用户都没有看到opacity: 0;

    $(window).on("load",function() {
    function fade() {
        var animation_height = $(window).innerHeight() * 0.25;
        var ratio = Math.round( (1 / animation_height) * 10000 ) / 10000;

        $('.fade').each(function() {

            var objectTop = $(this).offset().top;
            var windowBottom = $(window).scrollTop() + $(window).innerHeight();

            if ( objectTop < windowBottom ) {
                if ( objectTop < windowBottom - animation_height ) {
                    $(this).html( 'fully visible' );
                    $(this).css( {
                        transition: 'opacity 0.1s linear',
                        opacity: 1
                    } );

                } else {
                    $(this).html( 'fading in/out' );
                    $(this).css( {
                        transition: 'opacity 0.25s linear',
                        opacity: (windowBottom - objectTop) * ratio
                    } );
                }
            } else {
                $(this).html( 'not visible' );
                $(this).css( 'opacity', 0 );
            }
        });
    }
    $('.fade').css( 'opacity', 0 );
    fade();
    $(window).scroll(function() {fade();});
});

请在此处查看:http://jsfiddle.net/78xjLnu1/16/

干杯, 马丁

答案 2 :(得分:3)

我知道现在已经很晚了,但是我采用了原始代码并更改了一些内容来轻松控制css。所以我使用addClass()和removeClass()

创建了一个代码

此处为完整代码:http://jsfiddle.net/e5qaD/4837/

        if( bottom_of_window > bottom_of_object ){
            $(this).addClass('showme');
       }
        if( bottom_of_window < bottom_of_object ){
            $(this).removeClass('showme');

答案 3 :(得分:0)

对不起,这是老线程,但有些人仍然需要这个,我猜,

注意:我使用Animate.css库为fade设置了动画效果。

我使用了你的代码并添加了.hidden类(使用bootstrap的隐藏类)但你仍然可以定义 .hidden { opacity: 0; }

$(document).ready(function() {

/* Every time the window is scrolled ... */

$(window).scroll( function(){

/* Check the location of each desired element */
$('.hideme').each( function(i){

    var bottom_of_object = $(this).position().top + $(this).outerHeight();
    var bottom_of_window = $(window).scrollTop() + $(window).height();


    /* If the object is completely visible in the window, fade it it */
    if( bottom_of_window > bottom_of_object ){

        $(this).removeClass('hidden');
        $(this).addClass('animated fadeInUp');
    }    else {
            $(this).addClass('hidden');
               }

}); 
}); 
});

另一个注意事项:将此应用于容器可能会导致它出现故障。