【问题标题】:Add horizontal scroll indicator to DIV将水平滚动指示器添加到 DIV
【发布时间】:2021-04-23 03:57:52
【问题描述】:

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

经过一些测试,我很确定纯 CSS 不可能。 我在answer for a similar question 中找到了一个 sn-p。 不幸的是,我不知道如何根据需要更改脚本。

我正在使用一个简单的 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 和/或 jQuery 为滚动条指示器设置动画?

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

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

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

// 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);
});

【问题讨论】:

    标签: javascript html jquery css slider


    【解决方案1】:

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

    我做了一些修改并添加了一些js代码,查看下面的sn-p:

    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 处理程序中实现的那样

    【讨论】:

    • 谢谢!我会查一下。是否可以选择在单个页面上使用多个实例?
    • 不幸的是代码不起作用:codepen.io/cray_code/pen/yLaZdMP
    • 它工作正常,请尝试使用滚动条本身,(拖动它),您仍然需要添加更多类似的功能才能使用 Next 和 Prev 按钮
    • 谢谢!但我也尝试允许鼠标滚动。
    【解决方案2】:

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

    【讨论】:

      猜你喜欢
      • 2021-03-04
      • 1970-01-01
      • 1970-01-01
      • 2010-11-15
      • 2014-12-31
      • 2017-01-10
      • 2016-11-24
      • 2016-09-09
      • 2014-12-09
      相关资源
      最近更新 更多