如何在滚动时显示时间线的背景

问题描述

我有一些特定时间线的代码,问题是: 滚动时(顶部和底部)时间轴中的背景项目没有在正确的时间显示

当相关项垂直居中时,我需要显示背景,例如,在最后一个和倒数第二个背景中有一个显示偏移。

请看一下 GIF:https://gfycat.com/possiblesadcowbird

JS 代码(我取自:https://codepen.io/knyttneve/pen/bgvmma?editors=0010 并根据我的项目对其进行了编辑):

var fn_timeline = function() {
  $.fn.timeline = function() {
    var selectors = {
      id: $(this),item: $(this).find(".timeline-item"),activeClass: "timeline-item--active",img: ".o-timeline__img > img"
    };
    selectors.item.eq(0).addClass(selectors.activeClass);
    selectors.id.css("background-image","url(" + selectors.item.first().find(selectors.img).attr("src") + ")");

    var itemLength = selectors.item.length;
    $(window).scroll(function() {
      var max,min;
      var pos = $(this).scrollTop();
      selectors.item.each(function(i) {
        min = $(this).offset().top;
        max = ($(this).height() + $(this).offset().top);
        var that = $(this)
        if (i == itemLength - 2 && pos > min + $(this).height() / 2) {
          selectors.item.removeClass(selectors.activeClass);
          selectors.id.css("background-image","url(" + selectors.item.last().find(selectors.img).attr('src') + ")");
          selectors.item.last().addClass(selectors.activeClass)
        } else if (pos <= max - 40 && pos >= min) {
            selectors.id.css("background-image","url(" + $(this).find(selectors.img).attr('src') + ")");
            selectors.item.removeClass(selectors.activeClass);
            $(this).addClass(selectors.activeClass);
          }
      });
    });
  }
  $("#timeline-1").timeline();
}

HTML 代码

<div class="timeline-wrapper  container-content container-content--smaller container-content--fake-col   timeline1col  ">
  <div class="timeline-container" id="timeline-1" style="background-image: url(&quot;img/tl-3.jpg&quot;);">
    <div class="timeline">
      <div id="fullpage">
        <div class="section timeline-item-wrapper timeline-item">
          <div class="timeline-marker"></div>
          <div class="timeline__content">
            <div class="timeline-minature">
              <div class="o-timeline__img timeline-img">
                <img src="img/tl-1.jpg" style="width: 350px">
              </div>
            </div>

            <h2 class="timeline__content-title">Le premier ordinateur</h2>

            <div class="wysiwyg">
              He was born in 1881 (probably in the spring) in Salonica,then an ottoman city,Now inGreece. His father Ali Riza,a customs official turned lumber merchant,died when Mustafawas still a boy. His mother Zubeyde,adevout and strong-willed woman,raised him and his sister.
            </div>

            <a href="#" class="a-link--border-effect timeline-link">
              * Qu’est-ce que la géodésie ?
            </a>
          </div>
        </div>
        <div class="section timeline-item-wrapper timeline-item">
          <div class="timeline-marker"></div>
          <div class="timeline__content">
            <div class="timeline-minature">
              <div class="o-timeline__img timeline-img">
                <img src="img/tl-2.jpg" style="width: 350px">
              </div>
            </div>

            <p class="timeline__content-date">1991</p>

            <div class="wysiwyg">
              He was born in 1881 (probably in the spring) in Salonica,raised him and his sister.
            </div>

          </div>
        </div>
        <div class="section timeline-item-wrapper timeline-item timeline-item--active">
          <div class="timeline-marker"></div>
          <div class="timeline__content">
            <div class="timeline-minature">
              <div class="o-timeline__img timeline-img">
                <img src="img/tl-3.jpg" style="width: 350px">
              </div>
            </div>

            <h2 class="timeline__content-title">Le premier ordinateur</h2>

            <div class="wysiwyg">
              He was born in 1881 (probably in the spring) in Salonica,raised him and his sister.
            </div>

            <a href="#" class="a-link--border-effect timeline-link">
              * Qu’est-ce que la géodésie ?
            </a>
          </div>
        </div>
        <div class="section timeline-item-wrapper timeline-item">
          <div class="timeline-marker"></div>
          <div class="timeline__content">
            <div class="o-timeline__img timeline-bg">
              <img src="img/tl-4.jpg" alt="">
            </div>

            <h2 class="timeline__content-title">just bg</h2>

            <div class="wysiwyg">
              He was born in 1881 (probably in the spring) in Salonica,raised him and his sister.
            </div>

          </div>
        </div>
      </div>
    </div>
  </div>
</div>

解决方法

这是数学和用户体验设计问题的结合。 (正是我喜欢的那种问题!)

首先,您必须考虑用户是向上还是向下滚动。这是关键。
根据滚动方向,您将检查 item 顶部 OR 底部的位置。

例如,如果您只比较项目的顶部,则用户必须向上滚动整个项目,直到顶部越过中间,然后它才会变得模糊。那是不行的。

所以这真的是关于用户体验方面的: 当用户向下滚动时(因此内容向上移动),他需要在“某个点”显示下一个项目。 因为他可能还在看图片下方的文字,所以我觉得“点”在视口中间有点上方......但不是太高。

当用户向上滚动时(因此内容向下移动),他当然希望从上方看到的内容在视口中间之前不模糊。

所以...您需要考虑两个不同的视口位置。之后我称这些点为“触发”。

  • 中间稍上方(向下滚动)
  • 在顶部下方(向上滚动)

============

所以这变得越来越复杂...
两个滚动方向和两个视口位置以与顶部项目的底部进行比较。

所以我创建了两个变量来保存基于 4 个方面的条件结果:

  1. 向上或向下滚动
  2. 滚动像素小于项目的顶部或底部
  3. “触发器”大于项目的顶部
  4. “触发器”+ 20px 小于项目的底部(即避免闪烁...记住您在循环中)

我将两个“视口位置”定义为 5/163/16...
但是您可能更喜欢某些百分比值,例如 0.310.19...您可以使用它。

(function ($) {
  $.fn.timeline = function () {
    var selectors = {
      id: $(this),item: $(this).find(".timeline-item"),activeClass: "timeline-item--active",img: ".timeline__img"
    };

    // Onload,set first item as active
    selectors.item.eq(0).addClass(selectors.activeClass);

    // The viewport height
    var winHeight = $(window).height();

    // For the scrolling direction
    var lastPos = 0;

    // Scroll event handler
    $(window).scroll(function () {
      var item_bottom,item_top,item_height,scrollDown,trigger_top,trigger_bottom;

      // The window scrolled pixels
      var pos = $(this).scrollTop();

      // Scroll direction
      // true: user is scrolling down
      // false: user is scrolling up
      scrollDown = pos > lastPos;

      // items loop
      selectors.item.each(function (i) {
        var this_item = $(this);
        item_top = this_item.offset().top;
        item_height = this_item.height();
        item_bottom = item_height + this_item.offset().top;

        // You can play with those triggers...
        trigger_top = pos + (5 / 16) * winHeight;
        trigger_bottom = pos + (3 / 16) * winHeight;

        // Just for the console.log
        var item_date = this_item.find(".timeline__content-title").text();

        // The conditions
        var scroll_down_condition =
          scrollDown &&
          pos < item_top &&
          trigger_top >= item_top &&
          trigger_top + 20 <= item_bottom;

        var scroll_up_condition =
          !scrollDown &&
          pos < item_bottom &&
          trigger_bottom >= item_top &&
          trigger_bottom + 20 <= item_bottom;

        // If one or the other condition is true
        // Unblur the item and set the background
        if (scroll_down_condition || scroll_up_condition) {
          console.log(
            `Date ${item_date} is in view - `,`Scrolling ${scrollDown ? "down" : "up"}`
          );

          // Set background
          selectors.id.css(
            "background-image","url(" + this_item.find(selectors.img).attr("src") + ")"
          );

          // Remove the active class (unblur) on all items
          selectors.item.removeClass(selectors.activeClass);

          // Unblur
          this_item.addClass(selectors.activeClass);
        }
      }); // END item each

      // For the scrolling direction
      lastPos = pos;
    });
  };
})(jQuery);

CodePen