将水平滚动指示器添加到 DIV

Add horizontal scroll indicator to DIV

我想为可滚动 DIV 容器显示水平滚动指示器。

经过一些测试后,我很确定这不可能是纯粹的 CSS。 我在 中找到了一个片段。 不幸的是,我不知道如何根据我的需要更改脚本。

我正在使用一个简单的 DIV 容器,其中包含一些元素。 这是我的代码:

<div class="container">
    <div class="scroll-wrapper">
        <div class="scroll-container">
            <ul class="list-inline text-white text-center">
            
                <li class="list-inline-item" style="width: 200px;">
                    <div class="py-5 bg-dark"><h1 class="py-5">1</h1></div>
                </li>
                <li class="list-inline-item" style="width: 400px;">
                    <div class="py-5 bg-dark"><h1 class="py-5">2</h1></div>
                </li>
                [....]
            
            </ul>
        </div>
    </div>
    
    <div class="scroll-indicator">
        <div class="scroll-indicator-bar"></div>
    </div>
    
    <div class="d-flex justify-content-between">
        <button>Prev</button>
        <button>Next</button>
    </div>
</div>

和 CSS:

.scroll-wrapper {
    width: 100%;
    overflow-x: scroll;
    overflow-y: hidden;
    position: relative;
    white-space: nowrap;
}

.scroll-indicator {height: 4px; width: 100%; background-color: #ddd; margin-bottom: 2rem;}

.scroll-indicator-bar {height: 4px; width: 20%; background-color: #000;}

Working example

有什么方法可以用 CSS and/or jQuery 来设置滚动条指示器的动画吗?

编辑:我在这里找到了另一个很好的例子:https://codepen.io/mahish/pen/RajmQw

我尝试使用示例中的代码,但 prev/next 按钮不起作用。而且我也不知道如何使用滚动位置来显示和移动滚动指示器。

这是示例中的 JS 代码(更改为我的 class 名称):

// duration of scroll animation
var scrollDuration = 300;
// paddles
var leftPaddle = document.getElementsByClassName('left-paddle');
var rightPaddle = document.getElementsByClassName('right-paddle');
// get items dimensions
var itemsLength = $('.item').length;
var itemSize = $('.item').outerWidth(true);
// get some relevant size for the paddle triggering point
var paddleMargin = 20;

// get wrapper width
var getMenuWrapperSize = function() {
    return $('.scroll-wrapper').outerWidth();
}
var menuWrapperSize = getMenuWrapperSize();
// the wrapper is responsive
$(window).on('resize', function() {
    menuWrapperSize = getMenuWrapperSize();
});
// size of the visible part of the menu is equal as the wrapper size 
var menuVisibleSize = menuWrapperSize;

// get total width of all menu items
var getMenuSize = function() {
    return itemsLength * itemSize;
};
var menuSize = getMenuSize();
// get how much of menu is invisible
var menuInvisibleSize = menuSize - menuWrapperSize;

// get how much have we scrolled to the left
var getMenuPosition = function() {
    return $('.scroll-container').scrollLeft();
};

// finally, what happens when we are actually scrolling the menu
$('.scroll-container').on('scroll', function() {

    // get how much of menu is invisible
    menuInvisibleSize = menuSize - menuWrapperSize;
    // get how much have we scrolled so far
    var menuPosition = getMenuPosition();

    var menuEndOffset = menuInvisibleSize - paddleMargin;

    // show & hide the paddles 
    // depending on scroll position
    if (menuPosition <= paddleMargin) {
        $(leftPaddle).addClass('hidden');
        $(rightPaddle).removeClass('hidden');
    } else if (menuPosition < menuEndOffset) {
        // show both paddles in the middle
        $(leftPaddle).removeClass('hidden');
        $(rightPaddle).removeClass('hidden');
    } else if (menuPosition >= menuEndOffset) {
        $(leftPaddle).removeClass('hidden');
        $(rightPaddle).addClass('hidden');
}

    // print important values
    $('#print-wrapper-size span').text(menuWrapperSize);
    $('#print-menu-size span').text(menuSize);
    $('#print-menu-invisible-size span').text(menuInvisibleSize);
    $('#print-menu-position span').text(menuPosition);

});

// scroll to left
$(rightPaddle).on('click', function() {
    $('.scroll-container').animate( { scrollLeft: menuInvisibleSize}, scrollDuration);
});

// scroll to right
$(leftPaddle).on('click', function() {
    $('.scroll-container').animate( { scrollLeft: '0' }, scrollDuration);
});

您可以使用 vanilla js 拥有自己的自定义水平滚动行为,您只需要处理 mousedownmouseupmousemove 事件,计算所需的滚动值并移动您的使用 transform: translateX() 样式的元素,并跟踪这些值,

我做了一些更改并添加了一些 js 代码,检查下面的代码段:

const scrollBar = document.getElementById('myBar');
const scrollBarWrapper = document.getElementById('barWrapper');
const scrollContent = document.getElementById('scroll-container');

scrollBar.style.width =  ((scrollContent.offsetWidth * scrollBarWrapper.offsetWidth) / scrollContent.scrollWidth) + 'px';

let isScrolling = false;
let cursorX = 0;
let translateXValue = 0;

scrollBar.addEventListener('mousedown', function(e) {
    e.preventDefault();
    isScrolling = true;
    cursorX = e.clientX;
});

document.addEventListener('mouseup', function(e) {
    if (isScrolling) {
        e.preventDefault();
        isScrolling = false;
        translateXValue += (e.clientX - cursorX);
    }
});

document.addEventListener('mousemove', function(e) {
    if (isScrolling && cursorX !== e.clientX) {
        e.preventDefault();
        const translateAmount = (translateXValue + (e.clientX - cursorX));
        const scrollLength = (barWrapper.offsetWidth - scrollBar.offsetWidth);
        const barScroll = Math.min(Math.max(0, translateAmount), scrollLength);
        const contentTranslateRatio = (barScroll * scrollContent.scrollWidth) / scrollContent.offsetWidth;
        
        scrollBar.style.transform = 'translateX(' + barScroll + 'px)';
        scrollContent.style.transform = 'translateX(' + -contentTranslateRatio + 'px)';
    }
});
.scroll-wrapper {
    width: 100%;
    overflow: hidden;
    position: relative;
    white-space: nowrap;
}

.scroll-indicator {height: 6px; width: 100%; background-color: #ddd; margin-bottom: 2rem;}

.scroll-indicator-bar {height: 6px; width: 20%; background-color: #000;}
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" rel="stylesheet"/>
<div class="container" id="container">
    <div class="scroll-wrapper">
        <div class="scroll-container" id="scroll-container">
            <ul class="list-inline text-white text-center">
            
                <li class="list-inline-item" style="width: 200px;">
                    <div class="py-5 bg-dark"><h1 class="py-5">1</h1></div>
                </li>
                <li class="list-inline-item" style="width: 400px;">
                    <div class="py-5 bg-dark"><h1 class="py-5">2</h1></div>
                </li>
                <li class="list-inline-item" style="width: 300px;">
                    <div class="py-5 bg-dark"><h1 class="py-5">3</h1></div>
                </li>
                <li class="list-inline-item" style="width: 150px;">
                    <div class="py-5 bg-dark"><h1 class="py-5">4</h1></div>
                </li>
                <li class="list-inline-item" style="width: 250px;">
                    <div class="py-5 bg-dark"><h1 class="py-5">5</h1></div>
                </li>
                <li class="list-inline-item" style="width: 300px;">
                    <div class="py-5 bg-dark"><h1 class="py-5">6</h1></div>
                </li>
                <li class="list-inline-item" style="width: 200px;">
                    <div class="py-5 bg-dark"><h1 class="py-5">7</h1></div>
                </li>
                <li class="list-inline-item" style="width: 400px;">
                    <div class="py-5 bg-dark"><h1 class="py-5">8</h1></div>
                </li>
                <li class="list-inline-item" style="width: 300px;">
                    <div class="py-5 bg-dark"><h1 class="py-5">9</h1></div>
                </li>
            
            </ul>
        </div>
    </div>
    
    <div class="scroll-indicator" id="barWrapper">
        <div class="scroll-indicator-bar"  id="myBar"></div>
    </div>
    
    <div class="d-flex justify-content-between">
        <button>Prev</button>
        <button>Next</button>
    </div>
</div>

通过这段代码你有一个基于内容的动态滚动条宽度动态宽度,你可以管理你自己的滚动行为,

然后,您可以添加自定义 next() 和 previous() 函数来为滚动条和内容添加翻译,如在 mousemove 处理程序中实现的那样

我找到了使用 SimpleBar 的解决方案:https://github.com/Grsmto/simplebar/tree/master/packages/simplebar