在向下滚动时淡入,在向上滚动时淡出 - 基于窗口中的元素位置 [英] Fade In on Scroll Down, Fade Out on Scroll Up - based on element position in window

查看:222
本文介绍了在向下滚动时淡入,在向上滚动时淡出 - 基于窗口中的元素位置的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm trying to get a series of elements to fade in on scroll down when they are fully visible in the window. If I keep scrolling down, I do not want them to fade out, but if I scroll up, I do want them to fade out.

这是最接近的jsfiddle我找到了。
http://jsfiddle.net/tcloninger/e5qaD/

This is the closest jsfiddle I've found. 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);

        }    
    }); 
}); 
});

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

It does exactly what I want on scroll down, but I also want the elements to fade out if I scroll up past them.

我试了这个没有运气。

            if( bottom_of_window > bottom_of_object ){

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

            } else {

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

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

Thanks so much for taking the time to look at this.

推荐答案

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

The reason your attempt wasn't working, is because the two animations (fade-in and fade-out) were working against each other.

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

Right before an object became visible, it was still invisible and so the animation for fading-out would run. Then, the fraction of a second later when that same object had become visible, the fade-in animation would try to run, but the fade-out was still running. So they would work against each other and you would see nothing.

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

Eventually the object would become visible (most of the time), but it would take a while. And if you would scroll down by using the arrow-button at the button of the scrollbar, the animation would sort of work, because you would scroll using bigger increments, creating less scroll-events.

足够的解释,解决方案(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
});

.fade {
  margin: 50px;
  padding: 50px;
  background-color: lightgreen;
  opacity: 1;
}

<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>


小提琴: http://jsfiddle.net/eLwex993/2/

(fiddle: http://jsfiddle.net/eLwex993/2/)


  • 我将fade-codeline包装在if子句中: if($(this).css(opacity )== 0){...} 。这确保只有当不透明度 0 时,对象才会淡入。淡出一样。这可以防止淡入和淡出相互对抗,因为现在只有两个中的一个同时在一个对象上运行。

  • 我改变了 .animate() .fadeTo()。它是jQuery的不透明度的专用函数,写入时间要短得多,而且可能比动画更轻。

  • 我将 .position()更改为 .offset()。这总是相对于身体计算,而位置是相对于父亲。对于你的情况,我认为偏移是要走的路。

  • 我改变了 $(窗口).height()改为 $(窗口).innerHeight()。根据我的经验,后者更可靠。

  • 直接在滚动处理程序之后,我在页面加载时使用 $(窗口)调用该处理程序.scroll( ); 。现在,您可以在页面上为 .fade 类提供所有需要的对象,并且在页面加载时应该不可见的对象将立即淡出。

  • 我从HTML和CSS中删除了 #container ,因为(至少对于这个答案)没有必要。 (我想也许你需要 height:2000px ,因为你使用 .position()而不是 .offset(),否则我不知道。当然可以把它留在你的代码中。)

  • I wrapped the fade-codeline in an if-clause: if ($(this).css("opacity")==0) {...}. This makes sure the object is only faded in when the opacity is 0. Same goes for fading out. And this prevents the fade-in and fade-out from working against each other, because now there's ever only one of the two running at one time on an object.
  • I changed .animate() to .fadeTo(). It's jQuery's specialized function for opacity, a lot shorter to write and probably lighter than animate.
  • I changed .position() to .offset(). This always calculates relative to the body, whereas position is relative to the parent. For your case I believe offset is the way to go.
  • I changed $(window).height() to $(window).innerHeight(). The latter is more reliable in my experience.
  • Directly after the scroll-handler, I invoke that handler once on page-load with $(window).scroll();. Now you can give all desired objects on the page the .fade class, and objects that should be invisible at page-load, will be faded out immediately.
  • I removed #container from both HTML and CSS, because (at least for this answer) it isn't necessary. (I thought maybe you needed the height:2000px because you used .position() instead of .offset(), otherwise I don't know. Feel free of course to leave it in your code.)

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

If you want opacity values other than 0 and 1, use the following code:

$(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
});

.fade {
  margin: 50px;
  padding: 50px;
  background-color: lightgreen;
  opacity: 1;
}

<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>


(小提琴) : http://jsfiddle.net/eLwex993/3/


  • 我在if子句中添加了一个阈值,请参阅下面的说明

  • 我创建了变量for函数开头的阈值 min / max 。在函数的其余部分中,引用了这些变量。这样,如果您想再次更改值,只需在一个地方进行。

  • 我还添加了 || pageLoad 到if子句。这是确保所有对象在页面加载时淡化到正确的不透明度所必需的。 pageLoad 是一个布尔值,当调用 fade()时,它作为参数发送。

    我必须将淡入淡出代码放在额外的函数fade(){...} 中,以便能够沿<$ c发送$ c> pageLoad 调用scroll-handler时的boolean。

    我没有看到任何其他方法,如果有其他人这样做,请发表评论。

  • I added a threshold to the if-clause, see explanation below.
  • I created variables for the threshold and for min/max at the start of the function. In the rest of the function these variables are referenced. This way, if you ever want to change the values again, you only have to do it in one place.
  • I also added || pageLoad to the if-clause. This was necessary to make sure all objects are faded to the correct opacity on page-load. pageLoad is a boolean that is send along as an argument when fade() is invoked.
    I had to put the fade-code inside the extra function fade() {...}, in order to be able to send along the pageLoad boolean when the scroll-handler is invoked.
    I did't see any other way to do this, if anyone else does, please leave a comment.

说明:

你的小提琴 不起作用,是因为实际的不透明度值总是有点偏差从您设置的值。因此,如果将不透明度设置为 0.3 ,则实际值(在本例中)为 0.300000011920929 。这只是你必须通过追踪和错误一路学习的小错误之一。这就是为什么这个if子句不起作用的原因: if($(this).css(opacity)== 0.3){...}

Explanation:
The reason the code in your fiddle didn't work, is because the actual opacity values are always a little off from the value you set it to. So if you set the opacity to 0.3, the actual value (in this case) is 0.300000011920929. That's just one of those little bugs you have to learn along the way by trail and error. That's why this if-clause won't work: if ($(this).css("opacity") == 0.3) {...}.

我添加了一个阈值,考虑到这一差异: == 0.3 变为< = 0.31

(我已将阈值设置为 0.01 ,这当然可以改变,只是只要实际不透明度将落在设定值和此阈值之间。)

I added a threshold, to take that difference into account: == 0.3 becomes <= 0.31.
(I've set the threshold to 0.01, this can be changed of course, just as long as the actual opacity will fall between the set value and this threshold.)

现在,运算符从更改== < = > =

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

$(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
});

.fade {
  margin: 50px;
  padding: 50px;
  background-color: lightgreen;
  opacity: 1;
}

<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>


(小提琴) : http://jsfiddle.net/eLwex993/5/

这篇关于在向下滚动时淡入,在向上滚动时淡出 - 基于窗口中的元素位置的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆