对于具有scroll-behavior: smooth;
的父元素,当单击子元素时,我试图滚动它,以使子元素在父元素中完全可见。如果它只需要水平或垂直滚动,这很好,但当它必须同时进行这两项操作时(例如,孩子在右下角,只能部分看到(,它就会失败。单击处理程序正在计算向父对象的scrollTop
和scrollLeft
属性添加/减去哪些值。我注意到,如果我在设置scrollLeft
(但不是scrollTop
(前后放置一个延迟大于滚动过渡时间的setTimeout()
,那么它就可以工作(但看起来很做作(。有没有办法同时进行X和Y平滑滚动?
这里有一些伪代码,这样你就可以了解我正在做的事情:
HTML
<div id="grid">
<div class="row">
<div id="cell-1" class="cell"> 1 </div>
<div id="cell-2" class="cell"> 2 </div>
...
</div>
...
</div>
CSS
#grid {
height: 100vh;
overflow: scroll;
scroll-behavior: smooth;
}
.row {
display: flex;
}
.cell {
flex: 1 0 auto;
border: 2px dashed gray;
width: 250px;
height: 100px;
margin: 5px;
padding: 10px;
}
JS-
let grid = document.querySelector('#grid');
document.addEventListener('click', function (e) {
if (e.target.classList.contains('cell')) {
... (omitted a bunch of code to obtain cell/grid X/Y bounds) ...
if (cellRightBound > gridRightBound) {
let scroll = cellRightBound - gridRightBound + halfCellWidth;
grid.scrollLeft += scroll;
console.log('scrolled right ' + scroll);
} else if (cellLeftBound < gridLeftBound) {
let scroll = gridLeftBound - cellLeftBound + halfCellWidth;
if (scroll > 0) {
grid.scrollLeft -= scroll;
console.log('scrolled left ' + scroll);
}
}
if (cellBottomBound > gridBottomBound) {
let scroll = cellBottomBound - gridBottomBound + halfCellHeight;
grid.scrollTop += scroll;
console.log('scrolled down ' + scroll);
} else if (cellTopBound < gridTopBound) {
let scroll = gridTopBound - cellTopBound + halfCellHeight;
if (scroll > 0) {
grid.scrollTop -= scroll;
console.log('scrolled up ' + scroll);
}
}
}
});
因此,答案是使用grid.scrollTo({left: scrollLeft, top: scrollTop})
,并将变量scrollLeft
和scrollTop
设置为与正在设置的grid.scrollLeft
和grid.scrollTop
相同。例如:
let scrollLeft, scrollTop;
if (cellRightBound > gridRightBound) {
let scroll = cellRightBound - gridRightBound + halfCellWidth;
scrollLeft = grid.scrollLeft + scroll;
console.log('scrolled right ' + scroll);
} else if (cellLeftBound < gridLeftBound) {
let scroll = gridLeftBound - cellLeftBound + halfCellWidth;
if (scroll > 0) {
scrollLeft = grid.scrollLeft - scroll;
console.log('scrolled left ' + scroll);
}
}
if (cellBottomBound > gridBottomBound) {
let scroll = cellBottomBound - gridBottomBound + halfCellHeight;
scrollTop = grid.scrollTop + scroll;
console.log('scrolled down ' + scroll);
} else if (cellTopBound < gridTopBound) {
let scroll = gridTopBound - cellTopBound + halfCellHeight;
if (scroll > 0) {
scrollTop -= grid.scrollTop - scroll;
console.log('scrolled up ' + scroll);
}
}
if (scrollLeft !== undefined || scrollTop !== undefined) {
if (scrollLeft === undefined)
scrollLeft = grid.scrollLeft;
if (scrollTop === undefined)
scrollTop = grid.scrollTop;
grid.scrollTo({left: scrollLeft, top: scrollTop, behavior: 'smooth'});
}