首页 > 解决方案 > Vanilla JS 中的动量水平滚动

问题描述

我目前正在做一个需要水平滑块的项目。我把这个滑块做成可拖动的,并找到了一些让它随着动量滑动的代码。我设法用鼠标滚轮制作了这个水平滚动,但我不知道如何使它与这种动量效应一起工作。我能怎么做 ?

Lorem ipsum dolor sit amet, consectetur adipiscing elit。前庭 nec dapibus leo。Nunc odio massa, tempor eu aliquam vel, viverra vitae est. Suspendisse dignissim nisi arcu。Vivamus non sem et mi auctor varius。类 aptent taciti socialsqu ad litora torquent per conubia nostra, per inceptos himenaeos。Proin blandit malesuada sem, vel gravida tortor volutpat nec。Ut eu前庭neque。

(对不起,但我认为我不能更精确,我需要向您展示代码以使您理解)

// Slider dragging

const slider = document.querySelector('.slider');
let isDown = false;
let startX;
let scrollLeft;

slider.addEventListener('mousedown', (e) => {
    isDown = true;
    slider.classList.add('active');
    startX = e.pageX - slider.offsetLeft;
    scrollLeft = slider.scrollLeft;
    cancelMomentumTracking();
});

slider.addEventListener('mouseleave', () => {
    isDown = false;
    slider.classList.remove('active');
});

slider.addEventListener('mouseup', () => {
    isDown = false;
    slider.classList.remove('active');
    beginMomentumTracking();
});

slider.addEventListener('mousemove', (e) => {
    if(!isDown) return;
    e.preventDefault();
    const x = e.pageX - slider.offsetLeft;
    const walk = (x - startX); //scroll-fast
    var prevScrollLeft = slider.scrollLeft;
    slider.scrollLeft = scrollLeft - walk;
    velX = slider.scrollLeft - prevScrollLeft;
});

// Momentum 

var velX = 0;
var momentumID;

slider.addEventListener('wheel', (e) => {
    cancelMomentumTracking();
});  

function beginMomentumTracking(){
    cancelMomentumTracking();
    momentumID = requestAnimationFrame(momentumLoop);
}

function cancelMomentumTracking(){
    cancelAnimationFrame(momentumID);
}

function momentumLoop(){
    slider.scrollLeft += velX * 2;
    velX *= 0.95; 
    if (Math.abs(velX) > 0.5){
        momentumID = requestAnimationFrame(momentumLoop);
    }
}

//Scroll

const scrollContainer = document.querySelector(".slider");

scrollContainer.addEventListener("wheel", (evt) => {
    evt.preventDefault();
    scrollContainer.scrollLeft += evt.deltaY;
});
.slider {
    display: flex;
    width: 100vw;
    height: 75vh;
    cursor: grab;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    -ms-overflow-style: none;
    scrollbar-width: none;
}

.slider:active {
    cursor: grabbing;
}

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

.slide {
    margin: auto;
    margin-left: 3rem;
    flex-shrink: 0;
    width: 70%;
    height: 80%;
    background-color: crimson;
}

.slide:last-child {
    margin-right: 3rem;
}
<div class="slider" data-scroll-container="">
            <div class="slide" id="slide-1"></div>
            <div class="slide" id="slide-2"></div>
            <div class="slide" id="slide-3"></div>
            <div class="slide" id="slide-4"></div>
            <div class="slide" id="slide-5"></div>
        </div>

标签: javascripthtmlcss

解决方案


将此添加到您的函数中。它不像我希望的那样顺利,但它可以完成工作:

scrollContainer.addEventListener("wheel", (evt) => {
    // scrollContainer.scrollLeft += evt.deltaY;

    window.requestAnimationFrame(() => {
        scrollContainer.scrollTo({ top: 0, left: scrollContainer.scrollLeft + (evt.deltaY * 2), behavior: "smooth" });
    });
});

我所做的是用具有行为参数的操作替换了scrollLeft操作。我还补充说,就我而言,它滚动不够。scrollTosmoothevt.deltaY * 2

我想改进的是使用滚轮时的滚动捕捉和更少的“jankyness”。

在此处查看演示(滚动到蓝色/紫色框) - JavaScript 平滑水平滚动

JavaScript 平滑水平滚动


推荐阅读