Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
517 views
in Technique[技术] by (71.8m points)

javascript - 交叉口观察员不可信吗?(Intersection Observer is not trustable?)

I am changing the background color of a table cell when it is fully visible.(当表格单元格完全可见时,我将更改其背景颜色。)

To accomplish this task I have used an intersection observer.(为了完成此任务,我使用了交叉口观察器。)

All the code is available on code sandbox with demo reproducing the bug:(所有代码都可以在代码沙箱中获得,演示重现了该错误:)

编辑破晓日落9ki0d

I am using useInView hook for the intersection observer:(我在交叉观察器中使用useInView钩子:)

export const useInView = options => {
  const ref = useRef();
  const [isVisible, setIsVisible] = useState(false);
  const [intersectionRatio, setIntersectionRatio] = useState(false);

  useEffect(() => {
    const observer = new IntersectionObserver(([entry]) => {
      console.log("called");
      setIsVisible(entry.isIntersecting);
      setIntersectionRatio(entry.intersectionRatio);
    }, options);

    if (ref.current) observer.observe(ref.current);

    return () => {
      if (ref.current) observer.unobserve(ref.current);
    };
  }, [ref, options]);

  return [ref, isVisible, intersectionRatio];
};

Here is the table in which I am rendering the data:(这是我在其中渲染数据的表:)



 <div id="my-table" style={{ height: 200, width: 200, overflow: "auto" }}>
    <table>
      <tbody>
        {tableValues.map((row, rowIndex) => (
          <tr key={rowIndex}>
            {row.map((cell, cellIndex) => (
              <CellRendererContainer
                key={`${rowIndex}${cellIndex}`}
                rowIndex={rowIndex}
                cellIndex={cellIndex}
                tableCell={cell}
              />
            ))}
          </tr>
        ))}
      </tbody>
    </table>
  </div>

The intersection observer is used in CellRenderer, which is divided into two files:(相交观察器在CellRenderer中使用,分为两个文件:)

CellRendererContainer.js(CellRendererContainer.js)

const CellRendererContainer = ({ rowIndex, cellIndex, tableCell }) => {
  const [ref, isVisible, intersectionRatio] = useInView({
    root: document.querySelector("#my-table"),
    rootMargin: "0px",
    threshold: 0.0
  });

  return (
    <CellRenderer
      ref={ref}
      isVisible={isVisible}
      intersectionRatio={intersectionRatio}
      rowIndex={rowIndex}
      cellIndex={cellIndex}
      tableCell={tableCell}
    />
  );
};

And here is the actual rendering of the cell, CellRenderer.js(这是单元格的实际渲染CellRenderer.js)

const CellRenderer = React.forwardRef(
  ({ isVisible, intersectionRatio, rowIndex, cellIndex, tableCell }, ref) => (
    <td
      ref={ref}
      style={{
        padding: 25,
        backgroundColor:
          rowIndex > 0 && cellIndex > 0 && isVisible && intersectionRatio > 0.9
            ? "red"
            : "white"
      }}
    >
      {tableCell}
    </td>
  )
);

The problem in the current implementation is that: intersection observer's callback for some items is not being called.(当前实现中的问题在于:没有调用交叉观察者对某些项目的回调。)

Expected result:(预期结果:)

Any cell that becomes visible should have a red background as soon as it is visible fully.(完全可见的任何可见单元格应具有红色背景。)

Otherwise, that cell should be white.(否则,该单元格应为白色。)

Code sandbox link: (so that you does not need to scroll to the top)(代码沙箱链接:(因此您无需滚动到顶部))

编辑破晓日落9ki0d

  ask by Vishal translate from so

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

The IntersectionObserver constructor signature is:(IntersectionObserver构造函数签名为:)

var observer = new IntersectionObserver(callback[, options]);

The options argument is optional and, if supplied, should be an object with properties that describe how you'd like the newly created IntersectionObserver to behave.(options参数是可选的,如果提供的话,它应该是一个对象,该对象的属性描述您希望新创建的IntersectionObserver表现如何。)

In hook.js , you have this line:(在hook.js ,您具有以下这一行:)

const observer = new IntersectionObserver(([entry]) => {
  console.log("called");
  setIsVisible(entry.isIntersecting);
  setIntersectionRatio(entry.intersectionRatio);
}, options);

Your variable options isn't set to something that would be useful in this context.(您的变量options未设置为在这种情况下有用的options 。)

Instead, something like this does what you're looking for:(相反,这样的事情可以满足您的需求:)

const observer = new IntersectionObserver(([entry]) => {
  console.log("called");
  setIsVisible(entry.isIntersecting);
  setIntersectionRatio(entry.intersectionRatio);
}, {
  threshold: 0.9
});

After this change, the event would be triggered when the relevant elements become more or less than 90% visible.(进行此更改后,当相关元素变得大于或小于90%可见时,将触发事件。)


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...