javascript - 拆分列(每个 50%)以相反方向滚动 - 连续/循环

标签 javascript html jquery css infinite-scroll

编辑 仔细观察,在调整视口(viewport)大小时,这非常糟糕。它停止工作或在狭窄的窗口上工作,并且滚动速度 super 快。所以我把它放出来赏金!
--
我见过类似的东西,并一直在尝试重构 JS。我有两列内容,滚动时会朝相反的方向移动。这应该连续循环。
问题是如果我从 .project 中删除高度元素。向下滚动而不是向上滚动时,内容将平滑滚动。内容的高度/长度会有所不同,所以我在这里不能真正有一个固定值。
这似乎取决于视口(viewport)高度。如果 UI 的行为符合预期并且我减小了视口(viewport)的宽度,它可能会像上面描述的那样停止工作。但是,如果我随后降低高度 - 它可以再次开始正常运行。所以也许这取决于加载时视口(viewport)中有多少内容可见?
示例(也在代码片段中): https://jsfiddle.net/rdowb0y5/1
我将添加一个“媒体查询”,以便它仅在平板电脑/桌面 View 和移动设备上可见,JS 被删除并且内容只是堆叠。
在此先感谢 - 真的很期待对此的一些支持!

$(document).ready(function() {

    var num_children=$('.split-loop__left').children().length;
    var child_height=$('.split-loop__right').height() / num_children;
    var half_way=num_children * child_height / 2;
    $(window).scrollTop(half_way);

    function crisscross() {

      var parent=$(".split-loop"); //.first();
      var clone=$(parent).clone();

      var leftSide=$(clone).find('.split-loop__left');
      var rightSide=$(clone).find('.split-loop__right');

      if (window.scrollY > half_way) {
        //We are scrolling up
        $(window).scrollTop(half_way - child_height);

        var firstLeft=$(leftSide).children().first();
        var lastRight=$(rightSide).children().last();

        lastRight.appendTo(leftSide);
        firstLeft.prependTo(rightSide);

      }

      else if (window.scrollY < half_way - child_height) {

        var lastLeft=$(leftSide).children().last();
        var firstRight=$(rightSide).children().first();

        $(window).scrollTop(half_way);
        lastLeft.appendTo(rightSide);
        firstRight.prependTo(leftSide);
      }

      $(leftSide).css('bottom', '-'+ window.scrollY + 'px');
      $(rightSide).css('bottom', '-'+ window.scrollY + 'px');

      $(parent).replaceWith(clone);
    }

    $(window).scroll(crisscross);

  }

);
/* Hide Scroll Bars */

::-webkit-scrollbar {
  display: none;
}

html,
body {
  margin: 0;
  padding: 0;
  -ms-overflow-style: none;
  /* IE and Edge */
  scrollbar-width: none;
  /* Firefox */
}


/* Basic Styling */

img {
  border: 1px solid black;
  margin-bottom: 24px;
  width: 100%;
  max-width: 100%;
}

h2 {
  font-size: 14px;
  font-weight: normal;
  margin-bottom: 4px;
  font-family: 'Inter', sans-serif;
}

p {
  color: black;
  font-size: 11px;
  font-family: 'Inter', sans-serif;
}


/* Content will be in these eventually */

.bar-left,
.bar-right {
  border-right: 1px solid black;
  box-sizing: border-box;
  height: 100vh;
  position: fixed;
  top: 0;
  left: 0;
  width: 48px;
  z-index: 10000;
}

.bar-right {
  border: none;
  border-left: 1px solid black;
  left: auto;
  right: 0;
}


/* Split Loop */

.split-loop {
  position: relative;
  margin: 0 48px;
}

.split-loop__left {
  // position: absolute;
  // left: 0%;
  // top: 0%;
  // right: auto;
  // bottom: auto;
  // z-index: 4;
  width: 50%;
}

.split-loop__right {
  border-left: 1px solid black;
  box-sizing: border-box;
  position: fixed;
  right: 48px;
  bottom: 0;
  z-index: 5;
  width: calc(50% - 48px);
}

.project {
  box-sizing: border-box;
  border-bottom: 1px solid black;
  height: 600px;
  padding: 48px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.0/jquery.min.js"></script>

<header class="bar-left">

</header>

<div class="bar-right">

</div>

<div class="view">

  <div class="grid split-loop">

    <div class="split-loop__left">

      <div class="grid__item project">
        <img src="https://www.fillmurray.com/600/400" alt="" class="project__media" />
        <h2 class="project__title">Project Title</h2>
        <p class="project__desc">Short Description</p>
      </div>

      <div class="grid__item project">
        <img src="https://www.fillmurray.com/g/600/400" alt="" class="project__media" />
        <h2 class="project__title">Project Title</h2>
        <p class="project__desc">Short Description</p>
      </div>

      <div class="grid__item project">
        <img src="https://www.fillmurray.com/600/400" alt="" class="project__media" />
        <h2 class="project__title">Project Title</h2>
        <p class="project__desc">Short Description</p>
      </div>

    </div>

    <div class="split-loop__right">

      <div class="grid__item project">
        <img src="https://www.fillmurray.com/g/600/400" alt="" class="project__media" />
        <h2 class="project__title">Project Title</h2>
        <p class="project__desc">Short Description</p>
      </div>

      <div class="grid__item project">
        <img src="https://www.fillmurray.com/600/400" alt="" class="project__media" />
        <h2 class="project__title">Project Title</h2>
        <p class="project__desc">Short Description</p>
      </div>

      <div class="grid__item project">
        <img src="https://www.fillmurray.com/g/600/400" alt="" class="project__media" />
        <h2 class="project__title">Project Title</h2>
        <p class="project__desc">Short Description</p>
      </div>

    </div>

  </div>

</div>

最佳答案

Familytype.co 有以下限制:

  • 还需要一个滚动容器。他们在 body 上使用滚动条。
  • 两条车道必须具有相同的高度。他们的幻灯片有不同的高度,但都是 50vh 的倍数。他们设法拥有相同高度的车道。高度仍然基于视口(viewport)见他们的.block--50.block--100风格规则。
  • 您需要在同一 channel 中重复前两个元素才能看到平滑转移到第一张幻灯片。

  • 在以下,familytype.co 风格的方法中,我在左车道重复了前两个元素。然后在javascript中将左侧车道的所有元素克隆到右侧。还添加了一个媒体查询,如果视口(viewport)宽度低于 576 像素,则仅显示一条车道。

    let view, parent, leftSide, rightSide;
    
    $(document).ready(function() {
      view = $('#view');
      parent = $(".split-loop");
      leftSide = $(parent).find('.split-loop__left');
      rightSide = $(parent).find('.split-loop__right');
    
      centerScrollPosition();
      window.onresize = function(event) {
        centerScrollPosition();
      };
    
      //repeat first 2
      $(leftSide).append($($(leftSide).children()[0]).clone());
      $(leftSide).append($($(leftSide).children()[1]).clone());
      //clone left lane to right      
      let arr = [];
      $(leftSide).children().each((index, elm) => {
        arr.push($(elm).clone());
      });
    
      //shift right lane by half
      //arr.push.apply(arr, arr.splice(0, arr.length / 2));
      //arr.push(arr[0].clone());
      //arr.push(arr[1].clone());
      $(rightSide).append(arr);
    
      //listen to scroll events
      //incase you want movement to happen on user scroll
      $(view).add(window).scroll(function() {
        //$(view).on('wheel', function (event) {
        handleScroll();
      });
      handleScroll();
    
    });
    
    
    function centerScrollPosition() {
      //center the content
      var vh = $(window).height();
      var lh = leftSide.height();
      var half_way = (lh - vh) / 2;
      $(window).scrollTop(half_way);
    }
    
    function handleScroll() {
      var scroll = $(window).scrollTop();
      var sh = $(leftSide).height() - window.innerHeight;
    
      if (scroll >= (sh - 1)) {
        $(window).scrollTop(2);
      } else if (scroll == 0) {
        $(window).scrollTop(sh - 1);
      }
      $(rightSide).css({
        "transform": "translate3d(0, " + ((((sh) - scroll * 2) * -1)) + "px, 0)"
      });
    
    }
    * {
      box-sizing: border-box;
    }
    
     ::-webkit-scrollbar {
      display: none;
    }
    
    html,
    body {
      margin: 0;
      padding: 0;
      height: 100%;
      width: 100%;
      background-color: white;
    }
    
    body {
      overflow-y: scroll
    }
    
    
    /* Basic Styling */
    
    img {
      max-width: 90%;
      object-fit: fill;
      margin-top: 1rem;
      align-self: center;
      border: 1px solid black;
    }
    
    h2 {
      font-size: 14px;
      font-weight: normal;
      margin-bottom: 4px;
      font-family: 'Inter', sans-serif;
      text-align: center;
    }
    
    p {
      color: black;
      font-size: 11px;
      font-family: 'Inter', sans-serif;
      text-align: center;
    }
    
    
    /* center line for debugging */
    
    .center {
      position: fixed;
      width: 100vw;
      top: 50%;
      left: 0%;
      z-index: 100000;
      transform: translateY(-50%);
      border-bottom: 2px dashed gray;
    }
    
    
    /* Content will be in these eventually */
    
    .view {
      overflow: hidden;
      position: relative;
      width: 80vw;
      margin: 0 auto;
    }
    
    .bar-left,
    .bar-right {
      /*border-right: 1px solid black;*/
      box-sizing: border-box;
      height: 100vh;
      position: fixed;
      top: 0;
      left: 0;
      width: 5vw;
      z-index: 10000;
    }
    
    .bar-right {
      border: none;
      /*border-left: 1px solid black;*/
      left: auto;
      right: 0;
    }
    
    
    /* Split Loop */
    
    .split-loop {
      position: relative;
      width: 100%;
      height: 100%;
    }
    
    .split-loop>div {
      max-width: 50%;
      float: left;
      height: auto;
      transform-style: preserve-3d;
      display: flex;
      flex-flow: column;
    }
    
    .split-loop__right {
      will-change: transform;
      perspective: 1000;
      backface-visibility: hidden;
    }
    
    .project {
      border: 1px solid black;
      min-height: auto;
      background-color: lightskyblue;
      display: flex;
      flex-flow: column nowrap;
    }
    
    @media(max-width: 576px) {
      .split-loop>div {
        max-width: 100%;
      }
      .split-loop__right {
        display: none;
      }
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <!-- span class="center"></span -->
    <header class="bar-left"></header>
    <div class="bar-right"></div>
    
    <div id=view class="view">
      <div class="grid split-loop">
        <div class="split-loop__left">
          <div class="grid__item project">
            <img src="https://www.fillmurray.com/600/400" alt="" class="project__media" />
            <h2 class="project__title">Project Title 1</h2>
            <p class="project__desc">Short Description Lorem ipsum dolor sit amet consectetur adipisicing elit. Consequuntur, id?Short Description Lorem ipsum dolor sit amet consectetur adipisicing elit. Consequuntur, id?</p>
          </div>
    
          <div class="grid__item project">
            <img src="https://www.placecage.com/c/460/300" alt="" class="project__media" />
            <h2 class="project__title">Project Title 2</h2>
            <p class="project__desc">Short Description Lorem ipsum dolor sit amet.</p>
          </div>
    
          <div class="grid__item project">
            <img src="https://www.placecage.com/g/155/300" alt="" class="project__media" />
            <h2 class="project__title">Project Title 3</h2>
            <p class="project__desc">Short Description Lorem ipsum dolor sit amet consectetur, adipisicing elit. Aspernatur nostrum in obcaecati itaque explicabo voluptatibus corporis cumque praesentium eaque beatae!</p>
          </div>
          <div class="grid__item project">
            <img src="https://www.placecage.com/140/100" alt="" class="project__media" />
            <h2 class="project__title">Project Title 4</h2>
            <p class="project__desc">Short Description Lorem, ipsum dolor sit amet consectetur adipisicing elit. Dolores nobis eius, minus optio ab earum. Lorem ipsum dolor sit amet consectetur adipisicing elit. Architecto, at. Fuga nisi nulla laborum explicabo possimus repellendus
              amet quidem eos.</p>
          </div>
    
          <div class="grid__item project">
            <img src="https://www.stevensegallery.com/460/300" alt="" class="project__media" />
            <h2 class="project__title">Project Title 5</h2>
            <p class="project__desc">Short Description Lorem ipsum dolor sit amet consectetur adipisicing elit. Nihil?</p>
          </div>
    
          <div class="grid__item project">
            <img src="https://www.fillmurray.com/g/600/400" alt="" class="project__media" />
            <h2 class="project__title">Project Title 6</h2>
            <p class="project__desc">Short Description Lorem ipsum dolor, sit amet consectetur adipisicing elit. Quia iste distinctio doloremque facere!</p>
          </div>
        </div>
    
        <div class="split-loop__right">
    
        </div>
      </div>
    </div>

    第二车道需要更巧妙的布局。

    旧答案:
    我们可以使用转换来代替滚动条。解释在代码中:

        //variables to track left and right container scrolls
        var leftX = 0, rightX = 0;
        //how quickly shifts will happen
        //depends on how many images are in a column
        //range 1.0 - 5.0
        var shiftingThreshold = 1.7;
        var isAnimating = false;
        var parent, leftSide, rightSide;
    
    
        $(document).ready(function () {
          parent = $(".split-loop");
          leftSide = $(parent).find('.split-loop__left');
          rightSide = $(parent).find('.split-loop__right');
    
          centerScrollPosition();
          window.onresize = function (event) {
            centerScrollPosition();
          };
    
          document.querySelector('.split-loop__left').addEventListener('transitionend', () => {
            isAnimating = false;
            //positive value means clockwise
            //negative means counter clockwise
            //remove if you don't want to run loop
            //handleScroll(-125);
          });
    
          //listen to scroll events
          //incase you want movement to happen on user scroll
          $('#view').on('wheel', function (event) {
            handleScroll(event.originalEvent.deltaY);
          });
    
          //initiate continuous loop
          setTimeout(function () {
            //handleScroll(-125);
          }, 3000);
        });
    
        function centerScrollPosition() {
          //center the content
          var vh = $('#view').height();
          var slh = $('.split-loop__left').height();
          var half_way = (slh - vh) / 2;
          $('#view').scrollTop(half_way);
        }
    
        function handleScroll(deltaY) {
          //handle next scroll event only after last transition ends.
          if (isAnimating) {
            return;
          }
          isAnimating = true;
          var isUpShifted = true;
          var isJumped = true;
    
          leftX -= deltaY;
          rightX += deltaY;
    
          if (deltaY !== 0) {
            var childHeight = $('.split-loop__left').children().first().height();
            if ((leftX + childHeight / shiftingThreshold) <= 0) { //clockwise shift
              isUpShifted = true;
              var firstLeft = $(leftSide).children().first();
              var lastRight = $(rightSide).children().last();
    
              //shift left-first to right
              firstLeft.prependTo(rightSide);
    
              //shift right-last to left
              lastRight.appendTo(leftSide);
    
              leftX += childHeight + deltaY;
              rightX -= childHeight + deltaY;
    
            } else if ((leftX - childHeight / shiftingThreshold) > 0) { //anti clockwise shift
    
              isUpShifted = false;
              var lastLeft = $(leftSide).children().last();
              var firstRight = $(rightSide).children().first();
    
              //shift right-first to left
              firstRight.prependTo(leftSide);
              //shift left-last to right
              lastLeft.appendTo(rightSide);
    
              leftX -= childHeight - deltaY;
              rightX += childHeight - deltaY;
            } else {
              isJumped = false;
            }
    
            //if we've moved projects to other container then 
            //adjust position before smooth scrolling effect
            if (isJumped) {
              $('.split-loop__left').css('transform', 'translateY(' + leftX + 'px)');
              $('.split-loop__right').css('transform', 'translateY(' + rightX + 'px)');
              $('.split-loop__left').css('transition-duration', '0s');
              $('.split-loop__right').css('transition-duration', '0s');
              if (isUpShifted) {
                leftX -= deltaY;
                rightX += deltaY;
              } else {
                leftX -= deltaY;
                rightX += deltaY;
              }
            }
    
            //do smooth scroll effect
            setTimeout(function () {
              $('.split-loop__left').css('transition-duration', '1.5s');
              $('.split-loop__right').css('transition-duration', '1.5s');
              $('.split-loop__left').css('transform', 'translateY(' + leftX + 'px)');
              $('.split-loop__right').css('transform', 'translateY(' + rightX + 'px)');
            }, 5);
    
          }
    
        }
    * {
          box-sizing: border-box;
        }
    
        html,
        body {
          margin: 0;
          padding: 0;
          height: 100%;
          width: 100%;
          background-color: wheat;
        }
    
    
        /* Basic Styling */
        img {
          max-width: 80%;
          aspect-ratio: 6/4;
          object-fit: fill;
    
          margin-top: 10%;
          align-self: center;
          border: 1px solid black;
        }
    
        h2 {
          font-size: 14px;
          font-weight: normal;
          margin-bottom: 4px;
          font-family: 'Inter', sans-serif;
    
          text-align: center;
        }
    
        p {
          color: black;
          font-size: 11px;
          font-family: 'Inter', sans-serif;
          text-align: center;
        }
    
        /* center line for debugging */
        .center {
          position: fixed;
          width: 100vw;
          top: 50%;
          left: 0%;
          z-index: 100000;
          transform: translateY(-50%);
          border-bottom: 2px dashed gray;
        }
    
    
    
        /* Content will be in these eventually */
        .view {
          overflow: hidden;
          position: relative;
          width: 80vw;
          height: 100vh;
          margin: 0 auto;
        }
    
        .bar-left,
        .bar-right {
          /*border-right: 1px solid black;*/
          box-sizing: border-box;
          height: 100vh;
          position: fixed;
          top: 0;
          left: 0;
          width: 5vw;
          z-index: 10000;
        }
    
        .bar-right {
          border: none;
          /*border-left: 1px solid black;*/
          left: auto;
          right: 0;
        }
    
        /* Split Loop */
        .split-loop {
          position: relative;
          width: 100%;
          height: 100%;
        }
    
        .split-loop>div {
          max-width: 50%;
          float: left;
          transition-timing-function: linear;
          height: auto;
          will-change: transform;
        }
    
        .project {
          border: 1px solid black;
          min-height: 70vh;
          background-color: lightskyblue;
    
          display: flex;
          flex-flow: column nowrap;
        }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <!-- span class="center"></span -->
      <header class="bar-left"></header>
      <div class="bar-right"></div>
    
      <div id=view class="view">
        <div class="grid split-loop">
          <div class="split-loop__left">
            <div class="grid__item project">
              <img src="https://www.fillmurray.com/600/400" alt="" class="project__media" />
              <h2 class="project__title">Project Title 1</h2>
              <p class="project__desc">Short Description Lorem ipsum dolor sit amet consectetur adipisicing elit.
                Consequuntur, id?</p>
            </div>
    
            <div class="grid__item project">
              <img src="https://www.fillmurray.com/g/600/400" alt="" class="project__media" />
              <h2 class="project__title">Project Title 2</h2>
              <p class="project__desc">Short Description Lorem ipsum dolor sit amet.</p>
            </div>
    
            <div class="grid__item project">
              <img src="https://www.fillmurray.com/600/400" alt="" class="project__media" />
              <h2 class="project__title">Project Title 3</h2>
              <p class="project__desc">Short Description Lorem ipsum dolor sit amet consectetur, adipisicing elit.
                Aspernatur nostrum in obcaecati itaque explicabo voluptatibus corporis cumque praesentium eaque beatae!</p>
            </div>
    
          </div>
    
          <div class="split-loop__right">
            <div class="grid__item project">
              <img src="https://www.fillmurray.com/g/600/400" alt="" class="project__media" />
              <h2 class="project__title">Project Title 4</h2>
              <p class="project__desc">Short Description Lorem, ipsum dolor sit amet consectetur adipisicing elit. Dolores
                nobis eius, minus optio ab earum.</p>
            </div>
    
            <div class="grid__item project">
              <img src="https://www.fillmurray.com/600/400" alt="" class="project__media" />
              <h2 class="project__title">Project Title 5</h2>
              <p class="project__desc">Short Description Lorem ipsum dolor sit amet consectetur adipisicing elit. Nihil?</p>
            </div>
    
            <div class="grid__item project">
              <img src="https://www.fillmurray.com/g/600/400" alt="" class="project__media" />
              <h2 class="project__title">Project Title 6</h2>
              <p class="project__desc">Short Description Lorem ipsum dolor, sit amet consectetur adipisicing elit. Quia iste
                distinctio doloremque facere!</p>
            </div>
    
          </div>
        </div>
      </div>

    每列三个元素很少能在小视口(viewport)上平滑移动。你需要玩shiftingThreshold .

    关于javascript - 拆分列(每个 50%)以相反方向滚动 - 连续/循环,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70323333/

    相关文章:

    javascript - 使用 Turbolink 插件加载 javascript

    javascript - json兄弟数据

    jquery - 为什么 addBack 与 Find() 一起使用

    javascript - 让我的按钮类型 ="submit"打开另一个 Accordion

    javascript - 无法在 Laravel 5 中显示 Google map

    javascript - Jquery- noConflict() 不适合歌剧?

    html - 使用 HTML <img> 标签作为背景图片而不是 CSS background-image 属性?

    javascript - 单击表单中包含所需输入的提交按钮后如何重定向到另一个页面

    javascript - 如何使用Java脚本委托(delegate),在点击事件中使用每个函数值?

    javascript - 需要绘制一 strip 有平滑 Angular 的褪色线