**函数的作用,用overflow元素, 内部显示完整的行.
**
"currElement" @scroll='menuScrollX('currElement', 26)'>
<li>li>
....
let scrollValue = 0 // 把本次的scrollTop,写入变量用于判断滚动方向
let scrollTimer:any = null
// Y向滚动轴调整,用于完整显示 一行
function menuScrollY(elementID: string, rowHeight = 26) {
// 注意点:外部overflow元素的max-height高度, 应是 rowHeight 的倍数
// elementID: overflow元素的id
// rowHeight: overflow元素 内部行元素的行高
let rowNumber = 1 // 行数
const outElement = document.getElementById(elementID) as HTMLElement
// 顶部不调整,但要记录 scrollValue 值
if (outElement.scrollTop == 0) { scrollValue = 0;return }
// 如果 scrollTop 值 为行高的倍数 也不调整
if ((outElement.scrollTop % rowHeight) == 0) return
// 根据scrollValue 值 判断滚动方向, 计算行数
if (outElement.scrollTop > scrollValue) {
rowNumber = Math.ceil(outElement.scrollTop / rowHeight) // 向下滚动
} else {
rowNumber = Math.floor(outElement.scrollTop / rowHeight) // 向上滚动
}
// 使滚动的高度等于行高的倍数
// 问题点, 这时scrollTop 不停修正,页面会抖动
outElement.scrollTop = (rowNumber * rowHeight)
console.log('rowNumber', rowNumber,scrollValue)
scrollValue = outElement.scrollTop // 把本次的scrollTop,写入变量用于下次判断滚动方向
// 问题点, 滚动停下后 ,修正一次,页会抖动一次
// if (scrollTimer !== null) { clearTimeout(scrollTimer)}
// scrollTimer = setTimeout(() => {
// outElement.scrollTop = (rowNumber * rowHeight) // 使滚动的高度等于行高的倍数
// scrollTimer = null
// }, 200)
}
用seTimeout 页会抖动一次,不用滚动时, 会不停抖动,
说明我这方法有问题. 请教更好的方法
我看到网友的贴子,也指出类似的问题, 类似的方案不能平滑实现,目前没找到优化的方法
可以用mousewheel(chrome)和DOMMouseScroll(Firefox)控制鼠标滚轮事件,只会触发一次,不需要防抖,但是拖动滚动条没法触发scorll。
拖动滚动条scroll可以考虑调整容器scrollTop头为行高倍数
<style>
#container{overflow:auto;height:260px;border:solid 1px #aaa;max-width:680px;margin:0 auto}
#container>div.item{line-height:26px}
#container>div.item:nth-child(2n+1){background:#eee}
#container>div.item{text-align:center;font-weight:bold}
</style>
<div id="container">
<script>for (var i = 0; i < 50; i++)document.write(`<div class="item">${i}</div>`)</script>
</div>
<script>
let container = document.querySelector('#container');
let rowHeight = 26, rowNumber = 3;
let byMouseWheel = false;
function handleMouseWheel(e) {
e.preventDefault();
//deltaY(mousewheel有)和detail(DOMMouseScroll)小于0往上滚动
let dir = (e.deltaY || e.detail) < 0 ? -1 : 1;
byMouseWheel = true;
container.scrollTop += dir * rowHeight * rowNumber;
console.log(container.scrollTop, 'mousewheel')
setTimeout(() => { byMouseWheel = false }, 1)
}
container.addEventListener('mousewheel', handleMouseWheel);
container.addEventListener('DOMMouseScroll', handleMouseWheel)
let timer;
function handleScroll(e) {
if (byMouseWheel) return false;//鼠标滚轮事件不执行
console.log(container.scrollTop, 'scroll')
container.scrollTop -= container.scrollTop % rowHeight;//这样不会抖,但是触发多次比较耗资源
//防抖会跳一下,这个没法控制浏览器滚动的距离。除非改成隐藏容器自动生成的滚动条,改为用DOM模拟,拖动DOM用代码控制容器滚动,比如nicescroll
/*
clearTimeout(timer);
timer = setTimeout(() => {
container.scrollTop -= container.scrollTop % rowHeight
console.log(container.scrollTop,'scroll')
}, 150);*/
}
container.addEventListener('scroll', handleScroll, false);
</script>
let scrollValue = 0 // 把本次的scrollTop,写入变量用于判断滚动方向
let scrollTimer:any = null
// Y向滚动轴调整,用于完整显示 一行
function menuScrollY(elementID: string, rowHeight = 26) {
// 注意点:外部overflow元素的max-height高度, 应是 rowHeight 的倍数
// elementID: overflow元素的id
// rowHeight: overflow元素 内部行元素的行高
let rowNumber = 1 // 行数
const outElement = document.getElementById(elementID) as HTMLElement
let outElementScrollTop=outElement.scrollTop;
// 顶部不调整,但要记录 scrollValue 值
if (outElementScrollTop == 0) { scrollValue = 0;return }
// 如果 scrollTop 值 为行高的倍数 也不调整
if ((outElementScrollTop % rowHeight) == 0) return
// 根据scrollValue 值 判断滚动方向, 计算行数
if (outElementScrollTop > scrollValue) {
rowNumber = Math.ceil(outElementScrollTop / rowHeight) // 向下滚动
} else {
rowNumber = Math.floor(outElementScrollTop / rowHeight) // 向上滚动
}
// 使滚动的高度等于行高的倍数
// 问题点, 这时scrollTop 不停修正,页面会抖动
outElementScrollTop = (rowNumber * rowHeight)
console.log('rowNumber', rowNumber,scrollValue)
scrollValue = outElementScrollTop // 把本次的scrollTop,写入变量用于下次判断滚动方向
// 问题点, 滚动停下后 ,修正一次,页会抖动一次
// if (scrollTimer !== null) { clearTimeout(scrollTimer)}
// scrollTimer = setTimeout(() => {
// outElementScrollTop = (rowNumber * rowHeight) // 使滚动的高度等于行高的倍数
// scrollTimer = null
// }, 200)
}
这样更节省性能