为什么在滚动元素中使用 offset().top 和 scrollTop() 时我的尺寸没有按预期返回?

Why, using offset().top and scrollTop() within a scrolling element are my dimensions not returning as intended?

我正在这里开发一个网络应用 http://101drums.com/test and wish to fade in and out elements as they enter and leave the visible part of the scrolling parent element. I have been helped by the answer by myfunkyside in this question Fade In on Scroll Down, Fade Out on Scroll Up - based on element position in window and have adapted this code here https://jsfiddle.net/tciprop/u4vaodvL/。 但是,要么元素偏移顶部返回太大 and/or 滚动的可见部分 div 返回低,以便淡入淡出进入可见区域。有任何想法吗? 这是我的 Fiddle https://jsfiddle.net/tciprop/u4vaodvL/.

HTML

<div class="header"></div>
<div class="menu">
  <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 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>

CSS

body {
  overflow-x: hidden;
  overflow-y: hidden;
}
.header {
  height: 40px;
}
.fade {
  position: relative;
  margin: 10px 5px 10px 5px;
  padding: 10px 5px 10px 5px;
  background-color: lightgreen;
  opacity: 1;
  height: 50px;
}
.menu {
  position: relative;
  overflow-x: hidden;
  overflow-y: scroll;
  border: 2vw 3vh;
    width: 90vw;
  height: 80vh;
  margin: auto;
}

JS

$(window).on("load",function() {
  $(".menu").scroll(function() {
    $(".fade").each(function() {
        //find relative positions
        var objectTop = $(this).offset().top;
        var objectBottom = objectTop + $(this).outerHeight();
        var windowTop = $(".menu").scrollTop();
        var windowBottom = windowTop + $(".menu").innerHeight();

      if (objectTop < windowTop) {//fade out on leaving top of scrollable area
            if ($(this).css("opacity")==1) {
                    $(this).fadeTo(500,0);
            }
      } else if (objectBottom < windowBottom && objectTop > windowTop) {//fade in on entering top of scrollable area
            if ($(this).css("opacity")==0) {
                    $(this).fadeTo(500,1);
          }
      } else if (objectBottom < windowBottom) {//fade in on entering bottom of scrollable area
            if ($(this).css("opacity")==0) {
                    $(this).fadeTo(500,1);
          }
      } else {
            if ($(this).css("opacity")==1) {//fade out on leaving bottom of scrollable area
                    $(this).fadeTo(500,0);
            }
      }
     console.log(objectTop, objectBottom, windowTop, windowBottom);
    });
  }); $(".menu").scroll(); //invoke scroll-handler on page-load
});

修改这部分代码

var windowTop = $(".menu").scrollTop();
var windowBottom = windowTop + $(".menu").innerHeight();

使用window代替.menu

var windowTop = $(window).scrollTop();
var windowBottom = windowTop + $(window).innerHeight();

$(window).on("load", function() {
  $(".menu").scroll(function() {
    $(".fade").each(function() {
      //find relative positions
      var objectTop = $(this).offset().top;
      var objectBottom = objectTop + $(this).outerHeight();
      var windowTop = $(window).scrollTop();
      var windowBottom = windowTop + $(window).innerHeight();

      if (objectTop < windowTop) { //fade out on leaving top of scrollable area
        if ($(this).css("opacity") == 1) {
          $(this).fadeTo(500, 0);
        }
      } else if (objectBottom < windowBottom && objectTop > windowTop) { //fade in on entering top of scrollable area
        if ($(this).css("opacity") == 0) {
          $(this).fadeTo(500, 1);
        }
      } else if (objectBottom < windowBottom) { //fade in on entering bottom of scrollable area
        if ($(this).css("opacity") == 0) {
          $(this).fadeTo(500, 1);
        }
      } else {
        if ($(this).css("opacity") == 1) { //fade out on leaving bottom of scrollable area
          $(this).fadeTo(500, 0);
        }
      }
      console.log(objectTop, objectBottom, windowTop, windowBottom);
    });
  });
  $(".menu").scroll(); //invoke scroll-handler on page-load
});
body {
  overflow-x: hidden;
  overflow-y: hidden;
}
.header {
  height: 40px;
}
.fade {
  position: relative;
  margin: 10px 5px 10px 5px;
  padding: 10px 5px 10px 5px;
  background-color: lightgreen;
  opacity: 1;
  height: 50px;
}
.menu {
  position: relative;
  overflow-x: hidden;
  overflow-y: scroll;
  border: 2vw 3vh;
  width: 90vw;
  height: 80vh;
  margin: auto;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="header"></div>
<div class="menu">
  <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 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>

使用 .position().top 而不是 offset().top (我也做了一些其他更改,请参阅要点):

$(window).on("load",function() {
    $(".menu").scroll(function() {
        var parentBottom = $(this).innerHeight();
        $(".fade").each(function() {
            var objectTop = $(this).position().top;
            var objectBottom = objectTop + $(this).outerHeight();

            if (0 <= objectTop&&objectBottom < parentBottom) { //fade in when object is completely within view
                if ($(this).css("opacity")==0) {$(this).fadeTo(500,1);}
            } else { //fade out when object goes out of view (either top or bottom)
                if ($(this).css("opacity")==1) {$(this).fadeTo(500,0);}
            }
        });
    }).scroll(); //invoke scroll-handler on page-load
});

$(window).on("load",function() {
  $(".menu").scroll(function() {
    var parentBottom = $(this).innerHeight();
    $(".fade").each(function() {
      var objectTop = $(this).position().top;
      var objectBottom = objectTop + $(this).outerHeight();
      
      if (0 <= objectTop&&objectBottom < parentBottom) { //fade in when object is completely within view
        if ($(this).css("opacity")==0) {$(this).fadeTo(500,1);}
      } else { //fade out when object goes out of view (either top or bottom)
        if ($(this).css("opacity")==1) {$(this).fadeTo(500,0);}
      }
    });
  }).scroll(); //invoke scroll-handler on page-load
});
body {
  overflow-x: hidden;
  overflow-y: hidden;
}
.header {
  height: 40px;
  border: 2px solid red;
}
.menu {
  position: relative;
  width: 90vw;
  height: 80vh;
  margin: auto;
  border: 1px solid blue;
  border-width: 2vw 3vh;
  overflow-x: hidden;
  overflow-y: scroll;
}
.fade {
  position: relative;
  height: 50px;
  margin: 10px 5px;
  padding: 10px 5px;
  background-color: lightgreen;
  opacity: 1;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>

<div class="header"></div>
<div class="menu">
  <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 class="fade">Fade In 11</div>
  <div class="fade">Fade In 12</div>
  <div class="fade">Fade In 13</div>
  <div class="fade">Fade In 14</div>
  <div class="fade">Fade In 15</div>
  <div class="fade">Fade In 16</div>
  <div class="fade">Fade In 17</div>
  <div class="fade">Fade In 18</div>
  <div class="fade">Fade In 19</div>
  <div class="fade">Fade In 20</div>
</div>
jsfiddle: https://jsfiddle.net/2bc5ueLc/3/

  • .scrollTop 不再是必需的,我将其更改为 0
  • 我将 parentBottom (windowBottom) 移出了 .each,因为该值不会改变,因此只需要存储一次。
  • 我稍微简化了你的 if 子句。

更新

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

$(window).on("load",function() {
    $(".menu").scroll(function() {
        var parentBottom = $(this).innerHeight();
        $(".fade").each(function() {
            var objectHeight = $(this).outerHeight();
            var objectTop = $(this).position().top;
            var objectBottom = objectTop + objectHeight;

            //fade in/out based on visible percentage of element
            if (objectTop < 0) {
                if (objectBottom > 0) {$(this).fadeTo(0,objectBottom/objectHeight);}
                else if ($(this).css("opacity")!=0) {$(this).fadeTo(0,0);}
            } else if (objectBottom > parentBottom) {
                if (objectTop < parentBottom) {$(this).fadeTo(0,(parentBottom-objectTop)/objectHeight);}
                else if ($(this).css("opacity")!=0) {$(this).fadeTo(0,0);}
            } else if ($(this).css("opacity")!=1) {$(this).fadeTo(0,1);}
        });
    }).scroll(); //invoke scroll-handler on page-load
});

$(window).on("load",function() {
  $(".menu").scroll(function() {
    var parentBottom = $(this).innerHeight();
    $(".fade").each(function() {
      var objectHeight = $(this).outerHeight();
      var objectTop = $(this).position().top;
      var objectBottom = objectTop + objectHeight;
      
      //fade in/out based on visible percentage of element
      if (objectTop < 0) {
        if (objectBottom > 0) {$(this).fadeTo(0,objectBottom/objectHeight);}
        else if ($(this).css("opacity")!=0) {$(this).fadeTo(0,0);}
      } else if (objectBottom > parentBottom) {
        if (objectTop < parentBottom) {$(this).fadeTo(0,(parentBottom-objectTop)/objectHeight);}
        else if ($(this).css("opacity")!=0) {$(this).fadeTo(0,0);}
      } else if ($(this).css("opacity")!=1) {$(this).fadeTo(0,1);}
    });
  }).scroll(); //invoke scroll-handler on page-load
});
body {
  overflow-x: hidden;
  overflow-y: hidden;
}
.header {
  height: 40px;
  border: 2px solid red;
}
.menu {
  position: relative;
  width: 90vw;
  height: 80vh;
  margin: auto;
  border: 1px solid blue;
  border-width: 2vw 3vh;
  overflow-x: hidden;
  overflow-y: scroll;
}
.fade {
  position: relative;
  height: 50px;
  margin: 10px 5px;
  padding: 10px 5px;
  background-color: lightgreen;
  opacity: 1;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>

<div class="header"></div>
<div class="menu">
  <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 class="fade">Fade In 11</div>
  <div class="fade">Fade In 12</div>
  <div class="fade">Fade In 13</div>
  <div class="fade">Fade In 14</div>
  <div class="fade">Fade In 15</div>
  <div class="fade">Fade In 16</div>
  <div class="fade">Fade In 17</div>
  <div class="fade">Fade In 18</div>
  <div class="fade">Fade In 19</div>
  <div class="fade">Fade In 20</div>
</div>
jsfiddle: https://jsfiddle.net/2bc5ueLc/6/