javascript - 在宽度增加的元素中滚动时内容跳跃/不自然的移动

标签 javascript html reactjs scroll

我无法找到这个问题的答案,但我在许多应用程序(日历、议程等)中看到了这种确切的行为。正如您在下面的代码片段中看到的,我的 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 增加与元素宽度一样多。

enter image description here

相反,scrollLeft 的值保持不变,因此新框有效地“弹出”到 View 中:

enter image description here

正如您所提到的,由于 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/

相关文章:

javascript - 通过 attributes.getNamedItem 获取元素的实际宽度/高度值

javascript - 如何提取从API获取的JSON数据并传递到react-plotly?

javascript - NewRelic - 它有什么用?

javascript - 如何在路由更改后停止 setInterval 函数在 Angular Directive(指令)上执行

html - 双下拉 - 带 OVERFLOW 第 3 列子列表

javascript - 显示整个匹配单元格的脚本

html - 视口(viewport)大小更改时更改导航栏颜色 Bootstrap v4

javascript - Console.Log 没有在 React 构造函数中被调用

reactjs - 如何管理React Router组件的布局

javascript - React.js 中的抽象