将水平滚动指示器添加到 DIV
Posted
技术标签:
【中文标题】将水平滚动指示器添加到 DIV【英文标题】:Add horizontal scroll indicator to 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);
);
【问题讨论】:
【参考方案1】:您可以使用 vanilla js 拥有自己的自定义水平滚动行为,您只需要处理 mousedown
、mouseup
和 mousemove
事件,计算所需的滚动值并使用 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
【讨论】:
以上是关于将水平滚动指示器添加到 DIV的主要内容,如果未能解决你的问题,请参考以下文章
UIScrollView - 将视图移到前面,但在滚动指示器下方
如何在nativescript angular中隐藏ios的水平滚动指示器
ListView 中的点指示器 Flutter 中的水平滚动