1

我受到劳斯莱斯网站的启发,也想在我的网站中实现相同的滚动捕捉功能,我使用 HTML 默认值实现了它,scroll-snap-type这给了我预期的行为,但创建了两个滚动条,一个用于容器,另一个用于主体,哪个不出所料,所以我尝试使用,IntersectionObserver但它导致了一个问题,当直接从第一张幻灯片跳到第三张幻灯片时,我只能前往相邻的幻灯片。

这是代码沙箱链接:https ://codesandbox.io/s/scrollsnap-forked-pre0c?file=/pages/index.vue

这是我正在工作的代码

<template>
  <main class="landing">
    <nav class="scroller">
      <ul class="scroller__list">
        <li
          class="scroller__item"
          v-for="(slide, index) in slides"
          :key="index"
          @click.prevent="scroll(slide.id)"
        >
          <a
            class="scroller__dot"
            :href="'#' + slide.id"
            @click.prevent="scroll(slide.id)"
          ></a>
        </li>
      </ul>
    </nav>
    <div class="slides-container">
      <slide
        class="slide"
        v-for="(slide, index) in slides"
        :key="index"
        :img="slide.img"
        :id="slide.id"
        :format="slide.format"
        :filter="slide.filter"
        >{{ slide.content }}</slide
      >
    </div>
  </main>
</template>

<script lang="ts">
import Vue from "vue";

export default Vue.extend({
  data() {
    return {
      slides: [
        {
          img: "car-slide-1.png",
          content: "hello world",
          id: "car-slide-1",
          filter: "color-burn",
        },
        {
          img: "car-slide-2.png",
          // promo-video.mp4
          content: "Second Car",
          id: "car-slide-2",
          filter: "color-burn",
          // format: "video",
        },
        {
          img: "car-slide-3.png",
          content: "Third slide",
          id: "car-slide-3",
          filter: "color-burn",
        },
      ],
      observer: null as any as IntersectionObserver,
      options: {
        threshold: [0.5],
        root: process.browser
          ? document.getElementsByClassName("slides-container")[0]
          : null,
      } as IntersectionObserverInit,
    };
  },
  methods: {
    scroll(id: string, who: string | null = null) {
      console.log("scrolling to ", id, who ? "by " + who : "");
      document.getElementById(id)?.scrollIntoView({
        behavior: "smooth",
        block: "start",
      });
    },
  },
  mounted() {
    let scrolling = false;
    this.observer = new IntersectionObserver((entries, observer) => {
      entries.forEach((entry) => {
        if (entry.isIntersecting && !scrolling) {
          let top = entry.boundingClientRect.top;
          scrolling = true;
          window.scroll({ behavior: "smooth", top: window.pageYOffset + top });
        }
        scrolling = false;
      });
    }, this.options);
    document
      .querySelectorAll(".slide")
      .forEach((slide) => this.observer.observe(slide));
  },
});
</script>
4

0 回答 0