当鼠标滚轮:true 时,垂直滑动滑块内嵌套滚动

gen*_*ian 5 html javascript css scroll swiper.js

我有一个垂直滑块,我使用滑动器来浏览幻灯片。

每个 swiper-slide 容器高度为 100vh。

我有一张幻灯片,其内容大于视图高度,当使用鼠标滚轮滚动时,我想首先滚动其内容,当到达末尾或顶部时,根据滚动方向,移动到下一张或上一张幻灯片。

我浏览了 swiper 文档、SO 和其他页面,但没有找到解决方案。

这是jsfiddle: https://jsfiddle.net/gentian28/6wdsep1v/13/

超文本标记语言

<div class="swiper-container">
    <main class="main swiper-wrapper">

        <!-- landing -->
        <section id="home" class="swiper-slide">
            <div id="particles-js"></div>
            <div id="typeIt" class="d-flex align-center"></div>
        </section>

        <!-- about -->
        <section id="about" class="swiper-slide">
            <span class="animation">About</span>
        </section>

        <!-- portfolio -->
        <section id="portfolio" class="swiper-slide d-flex flex-wrap col-3">
            <div class="card">
                card 1
            </div>
            <div class="card">
                card 2
            </div>
            <div class="card">
                card 3
            </div>
            <div class="card">
                card 4
            </div>
            <div class="card">
                card 1
            </div>
            <div class="card">
                card 1
            </div>
            <div class="card">
                card 1
            </div>
            <div class="card">
                card 1
            </div>
            <div class="card">
                card 1
            </div>
            <div class="card">
                card 1
            </div>
            <div class="card">
                card 1
            </div>
        </section>

        <!-- technologies -->
        <section id="skills" class="swiper-slide">
            Skills
        </section>

        <!-- contact -->
        <section id="contact" class="swiper-slide">
            Contact
        </section>

    </main>

</div>
Run Code Online (Sandbox Code Playgroud)

CSS

body {
    margin: 0;
    padding: 0;
}
.d-flex {
    display: flex;
}
.align-center {
    align-items: center;
}
.justify-center {
    justify-content: center;
}
.justify-between {
    justify-content: space-between;
}
.flex-column {
    flex-flow: column;
}
.column-reverse {
    flex-flow: column-reverse;
}
.flex-wrap {
    flex-wrap: wrap;
}
.col-2 > * {
    width: calc(100% / 2 - 7.5px);
    margin-right: 15px;
    margin-bottom: 15px;
}
.col-2 > *:nth-child(2n) {
    margin-right: 0;
}

.col-3 > * {
    width: calc(100% / 3 - 10px);
    margin-right: 15px;
}

.col-3 > *:nth-child(3n) {
    margin-right: 0;
}

.col-4 > * {
    width: calc(100% / 4 - 10.5px);
    margin-right: 14px;
}

.col-4 > *:nth-child(4n) {
    margin-right: 0;
}
.card {
    height: 300px;
}

.swiper-container {
    width: 100% - 120px;
    height: 100vh;
    margin-left: auto;
    margin-right: auto;
}
.swiper-slide {
    text-align: center;
    font-size: 18px;
    background: #fff;
    /* Center slide text vertically */
    display: -webkit-box;
    display: -ms-flexbox;
    display: -webkit-flex;
    display: flex;
    -webkit-box-pack: center;
    -ms-flex-pack: center;
    -webkit-justify-content: center;
    justify-content: center;
    -webkit-box-align: center;
    -ms-flex-align: center;
    -webkit-align-items: center;
    align-items: center;
    overflow-y: auto;
}
.swiper-pagination {
    display: flex;
    flex-flow: column;
}
.swiper-pagination-bullet-active {
    opacity: 0;
}
.swiper-pagination-bullet {
    width: 120px;
    height: 96px;
    border-radius: 0;
    opacity: 0;
}
Run Code Online (Sandbox Code Playgroud)

JS

const swiperConf = {
    direction: 'vertical',
    slidesPerView: 1,
    spaceBetween: -1,
    mousewheel: true,
    keyboard: true,
    pagination: {
        el: '.swiper-pagination',
        clickable: true,
    }
}

var swiper = new Swiper('.swiper-container', swiperConf);
Run Code Online (Sandbox Code Playgroud)

小智 0

也遇到了这个问题,@Daryll 的小提琴非常有帮助,但是使用 typescript 从 HTMLElement 获取“swiperSlideSize”时存在一些问题(也使用reactjs存在一些差异)。这对我来说是“onSlideChangeTransitionEnd”的事件处理程序:

  const allowScroll = (swiper: SwiperEvent) => {
    var activeIndex = swiper.activeIndex;
    var activeSlide = swiper.slides[activeIndex];
    var { scrollHeight, clientHeight } = activeSlide;
    const diff = scrollHeight - clientHeight;
    if (diff > 0) {
      const findScroll = (e) => {
        const scrollUp = e.deltaY < 0;
        if (scrollUp && activeSlide.scrollTop === 0) {
          swiper.mousewheel.enable();
          activeSlide.removeEventListener("wheel", findScroll);
        } else if (!scrollUp && activeSlide.scrollTop === diff) {
          swiper.mousewheel.enable();
          activeSlide.scrollTop = 0;
          activeSlide.removeEventListener("wheel", findScroll);
        }
      };
      activeSlide.addEventListener("wheel", findScroll);
      swiper.mousewheel.disable();
    }
  };

Run Code Online (Sandbox Code Playgroud)

编辑:“SwiperEvent”类型是我正在使用的别名import { Swiper as SwiperEvent } from "swiper";避免命名空间冲突的别名import { Swiper } from "swiper/react";

编辑2:对于移动使用,您必须考虑“touchmove”事件,它不会(总是?)注册“wheel”事件。通过在滑动器上禁用“allowTouchMove”,您可以在移动设备上实现与mousewheel.disable()桌面设备相同的效果。这是该案例的一些代码:

  const allowScroll = (swiper: SwiperEvent) => {
    var activeIndex = swiper.activeIndex;
    var activeSlide = swiper.slides[activeIndex];
    var { scrollHeight, clientHeight } = activeSlide;
    const diff = scrollHeight - clientHeight;
    if (activeSlide.scrollTop === 0) activeSlide.scrollTop = 1;
    else if (activeSlide.scrollTop === diff) activeSlide.scrollTop = diff - 1;
    if (diff > 0) {
      const findScroll = (e) => {
        const scrollUp = e.deltaY < 0;
        if (
          (scrollUp || e.type === "touchmove") &&
          activeSlide.scrollTop <= 0
        ) {
          swiper.mousewheel.enable();
          swiper.allowTouchMove = true;
          activeSlide.removeEventListener("wheel", findScroll);
          activeSlide.removeEventListener("touchmove", findScroll);
        } else if (
          (!scrollUp || e.type === "touchmove") &&
          activeSlide.scrollTop >= diff
        ) {
          swiper.mousewheel.enable();
          swiper.allowTouchMove = true;
          activeSlide.removeEventListener("wheel", findScroll);
          activeSlide.removeEventListener("touchmove", findScroll);
        }
      };
      activeSlide.addEventListener("wheel", findScroll);
      activeSlide.addEventListener("touchmove", findScroll);
      swiper.mousewheel.disable();
      swiper.allowTouchMove = false;
    }
  };
Run Code Online (Sandbox Code Playgroud)

基本上,通过将scrollTop 设置为距离范围顶部或底部1px,可以防止 mousewheel.enable() 调用立即触发。在原始版本中,激活时幻灯片始终从滚动高度的顶部开始,而此版本如果您向下滑动到它,则从“顶部”(技术上向下 1px)开始,如果您“向下滑动”,则从“底部”开始重新向上滑动即可。