代码之家  ›  专栏  ›  技术社区  ›  Cray

在DIV中添加水平滚动指示器

  •  0
  • Cray  · 技术社区  · 4 年前

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

    经过一些测试,我非常确定纯CSS是不可能的。 我在一个 answer for a similar question . 不幸的是,我不知道如何根据我的需要更改脚本。

    我使用了一个简单的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);
    });
    
    0 回复  |  直到 4 年前
        1
  •  1
  •   Zac    4 年前

    您可以使用vanilla js自定义水平滚动行为,只需处理 mousedown , mouseup mousemove 事件,计算所需的滚动值,并使用以下命令移动元素 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处理程序中实现的那样

        2
  •  0
  •   Cray    4 年前

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