在 Svelte 中捕获滚动元素而不是 window

Capture scroll over element instead of window in Svelte

只有当用户在其上方的元素上启动向下垂直滚动事件时,我如何才能启用自动滚动到该元素的顶部?我想这样做,以便页面顶部的滚动操作启动平滑滑动并捕捉到下一个重要元素以达到 UI/UX 目的。我正在使用 Svelte。

<script>
    import Card from './Card.svelte';
    
    const cards = ["card1", "card2", "card3", "card4"]

    let y = 0;
    let lastY = 0;
    let theater;
    let upperContainer;

    const scrollToTheater = (y) => {
        let dy = lastY - y;
        lastY = y;

        if (dy < -10) {
            document.body.parentNode.scrollTo({
                top: theater.offsetTop,
                left: 0,
                behavior: 'smooth'
            })
        }
    }

    $: scrollToTheater(y);

</script>

<svelte:window bind:scrollY={y} />

<main>
    <header>
        <h1>Hello World!</h1>
    </header>
    <div id="upper-container" bind:this="{upperContainer}">
        <h2>Capture scroll over this area only</h2>
    </div>
    <div class="theater" bind:this="{theater}">
        {#each cards as card}
            <Card {card} />
        {/each}
    </div>
    <footer>
        Footer
    </footer>
</main>

<style>

    header {
        width: 100%;
        height: 40px;
        padding:10px 20px 0 0;
    }

    #upper-container {
        width: 100%;
        height: 50vw;
        margin: 30px 0;
        background-color: rebeccapurple;
    }
    
    .theater {
        background-color: black;
        overflow: hidden;
  }

</style>

这里是REPL。在 REPL 中,您可以看到虽然在紫色 div 上滚动时效果有效,但它会干扰从下方区域滚动。

我尝试通过删除以下替代方式编写滚动事件侦听器:

<svelte:window bind:scrollY={y} />

并添加:

<div id="upper-container" bind:this="{upperContainer}" on:scroll={() => {alert("scrolled")}}>

或:

onMount(() => {
    const upper_container = document.getElementById("upper-container");
    upper_container.addEventListener("scroll", () => alert("scroll"))
});

没有结果(请参阅 REPL 中注释掉的块)。如果我将“滚动”替换为“点击”,这些事件将按预期运行。我也尝试使用 getBoundingClientRect().bottom 来测试光标相对于元素的位置,但是当我将 upperContainer.getBoundingClientRect().bottom 放在 scrollToTheater 功能块中时, upperContainerundefined.

滚动事件只会在实际发生滚动时触发。在您的示例中,您正在寻找滚动来实现这一点的框中没有足够的内容。

这是您的 REPL 使用 onMount 技术将内容添加到框中并绑定到元素的内容。

这里是 REPL,容器上的 on:scroll 事件处理程序不需要绑定,两者都可以正常工作。

但是,如果您要跟踪的是鼠标滚轮在容器上滚动的时间,即使容器内没有足够的内容来触发滚动,那么您将需要使用 on:mousewheel 处理程序而不是此版本 REPL 中所示,您可能希望或可能不希望在执行此操作时阻止默认设置,它绝对不考虑移动用户,但这也有效。