我无法找到这个问题的答案,但我在许多应用程序(日历、议程等)中看到了这种确切的行为。正如您在下面的代码片段中看到的,我的 container
通过滚动到两侧而展开 - 新的 div
正在插入其中。当您向右滚动时,感觉还不错且自然,但是,当您向左滚动时,它总是会添加该元素,并且您停留在 0px
,需要向后滚动一点,然后再次向左滚动扩大一些。最好尝试以下操作:
import React, { useEffect, useState } from 'react';
import ReactDOM from 'react-dom/client';
function Test() {
const [span, setSpan] = useState<Array<number>>([-1, 0, 1]);
// Append item to the array - scrolling right
const append = () => {
setSpan([
...span,
span[span.length - 1] + 1,
]);
};
// Prepend item to the array - scrolling left
const prepend = () => {
setSpan([
span[0] - 1,
...span,
]);
};
// Center view on load - to the middle of element '0' - e.i. the center
useEffect(() => {
const element = document.getElementById('element-0');
if (element) {
element.scrollIntoView({ behavior: 'auto', inline: 'center' });
}
}, []);
// Register 'scroll' listener
useEffect(() => {
const element = document.getElementById('container');
const scrolling = () => {
if (element) {
if (element.scrollLeft === 0) {
prepend();
}
if (element.offsetWidth + element.scrollLeft >= (element.scrollWidth - 100)) {
append();
}
}
};
element.addEventListener('scroll', scrolling);
return () => {
element.removeEventListener('scroll', scrolling);
};
}, [span.length]);
return (
<div style={{
display: 'flex', alignItems: 'center', justifyContent: 'center',
}}
>
<div
id="container"
style={{
maxWidth: '50vw', maxHeight: '50vh', overflowX: 'auto', whiteSpace: 'nowrap', backgroundColor: 'red',
}}
>
<div style={{ width: 'fit-content' }}>
<div style={{ width: 'fit-content' }}>
<div style={{ display: 'flex' }}>
{span.map((element) => (
<div key={`element-${element}`} id={`element-${element}`} style={{ minWidth: '40vw', minHeight: '100vh', border: '1px solid black' }}>
{ element }
</div>
))}
</div>
</div>
</div>
</div>
</div>
);
}
const root = ReactDOM.createRoot(
document.getElementById('root')
);
root.render(
<React.StrictMode>
<Test />
</React.StrictMode>
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
在添加新项目之前,我尝试以编程方式向右滚动一点,但这只会产生更多问题。有没有简单的方法可以解决?
最佳答案
前置元素不会使其容器的 scrollLeft
增加与元素宽度一样多。
相反,scrollLeft
的值保持不变,因此新框有效地“弹出”到 View 中:
正如您所提到的,由于 scrollLeft
在插入后保持为零,因此进一步的鼠标滚轮移动不会导致容器滚动,因此 scroll
事件不会触发,因此不会评估框插入逻辑。
这可以解决,例如,通过监听 wheel
事件而不是滚动
。问题是,scrollLeft 仍将保持为零,因此这些框只会一一出现在 View 中,而不是让用户滚动到它们上。 Demo 。另外,鼠标滚轮并不是滚动的唯一方式。
因此,根据问题的定义,我们需要手动调整滚动位置,以便 View 保持与插入之前相同的元素。在本例中,该金额就是 offsetWidth
的盒子,所以解决方案可能如下:
Demo
const boxWidth = document.getElementById("element-0").offsetWidth;
if (element.scrollLeft < 100) {
element.scrollBy(boxWidth, 0);
prepend();
}
else if (/*...*/) {
我希望这回答了你的问题。 :)
关于javascript - 在宽度增加的元素中滚动时内容跳跃/不自然的移动,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72826716/