【问题标题】:Keep elements visible after first scroll using react-visibility-sensor使用 react-visibility-sensor 在第一次滚动后保持元素可见
【发布时间】:2022-02-24 13:44:07
【问题描述】:

使用 react-visibility-sensor 我创建了一个更高的组件来为我的项目的滚动部分设置动画。

我在尝试使其仅在第一个滚动时起作用时遇到了问题。 目前这些部分出现和消失。

任何帮助将不胜感激。干杯!

import VisibilitySensor from 'react-visibility-sensor';

export const SlideUp = ({ children }) => {
  const [isVisible, setVisibility] = useState(false);

  const onChange = visiblity => {
    setVisibility(visiblity);
  };

  return (
    <VisibilitySensor
      partialVisibility
      offset={{ top: 200 }}
      onChange={onChange}
    >
      <div
        style={{
          transition: `opacity ${0.5}s ease, transform ${0.5}s ease`,
          opacity: isVisible ? 1 : 0,
          transform: isVisible ? `translateY(${0}px)` : `translateY(${20}px)`,
        }}
      >
        {children}
      </div>
    </VisibilitySensor>
  );
};```

- use example:

<SlideUp>
  <Section />
</SlideUp>

【问题讨论】:

标签: reactjs scroll react-hooks


【解决方案1】:

我的解决方案是将 React Pose 与 React Visibility 混合使用。

可见性会触发 React Pose 中的动画,该动画仅发生一次。动画依赖于姿势而不是可见性。

import VisibilitySensor from 'react-visibility-sensor';
import posed from 'react-pose';

const PoseDiv = posed.div({
  enter: {
    y: 0,
    opacity: 1,
    transition: {
      duration: 300,
      ease: 'easeIn',
    },
  },
  exit: { y: 20, opacity: 0 },
});

export const SlideUp = ({ children }) => {
  const [isVisible, setVisibility] = useState(false);
  const [entered, setEntered] = useState(false);

  const onChange = visiblity => {
    setVisibility(visiblity);
  };

  useEffect(() => {
    if (isVisible) {
      setEntered(true);
    }
  }, [isVisible]);

  return (
    <>
      <VisibilitySensor
        partialVisibility
        offset={{ top: 100 }}
        onChange={onChange}
      >
        <PoseDiv pose={entered ? 'enter' : 'exit'}>{children}</PoseDiv>
      </VisibilitySensor>
    </>
  );
}; 

我希望它可以帮助其他人。干杯!

PS:由于 React Pose 现已弃用,因此需要更新此解决方案。

https://www.framer.com/api/motion/migrate-from-pose/

【讨论】:

    【解决方案2】:
    import VisibilitySensor from 'react-visibility-sensor';
    
    export const SlideUp = ({ children }) => {
      const [isVisible, setVisibility] = useState(false);
    
      const onChange = visiblity => {
        setVisibility(visiblity);
      };
    
      return (
        <VisibilitySensor
          partialVisibility
          offset={{ top: 200 }}
          onChange={onChange}
        >
          <div
            className={`example ${isVisible ? 'visible' : ''}`}
          >
            {children}
          </div>
        </VisibilitySensor>
      );
    };
    

    CSS

    .example{
      ...
      opacity: 0;
      transform: translateY(20px);
      transition: opacity 0.5s ease, transform 0.5s ease;
    }
    .example.visible{
      opacity: 1;
      transform: translateY(0px);
    }
    

    尝试使用className

    【讨论】:

    • 感谢您的回答,但它就像以前一样工作。 @zynkn
    【解决方案3】:

    我认为您正在切换可见性状态,以保持 ui 显示后可见,不要将状态更改为不可见

    改变一下

    const onChange = visiblity => {
       setVisibility(visiblity);
      };
    

    const onChange = visiblity => {
    if(visiblity){
     setVisibility(visiblity);
    }
    };
    

    【讨论】:

      【解决方案4】:

      这是我一直在使用的解决方案。只需使用hasBeenVisible 渲染道具而不是isVisible

      import React, { useState } from "react";
      import VisibilitySensor from "react-visibility-sensor";
      
      /**
       * VisibilitySensor does not implement some kind of funcionality to track first time
       * visibility. This component extends VisibilitySensor compoment to provide this
       * feature. Just use `hasBeenVisible` render prop instead of `isVisible`.
       * 
       * https://github.com/joshwnj/react-visibility-sensor/issues/117#issuecomment-686365798
       */
      const AppearSensor = ({
        onChange,
        children,
        ...rest
      }) => {
        const [hasBeenVisible, setHasBeenVisible] = useState(false);
      
        return (
          <VisibilitySensor {...rest} onChange={(isVisible) => {
            if (isVisible) setHasBeenVisible(true)
            if (onChange) onChange(isVisible)
          }}>
            {
              ({
                isVisible,
                ...restRenderProps
              }) => {
                return children({ isVisible, ...restRenderProps, hasBeenVisible })
              }
            }
          </VisibilitySensor>
        );
      };
      
      AppearSensor.propTypes = VisibilitySensor.propTypes
      AppearSensor.defaultProps = VisibilitySensor.defaultProps
      
      export default AppearSensor;
      
      【解决方案5】:

      如果您希望 div 一次淡入,则留在屏幕上。

      改变这个

        const onChange = visiblity => {
          setVisibility(visiblity);
        };
      

      到这里

        const onChange = visiblity => {
          if(visiblity)
            setVisibility(true);
        };
      

      【讨论】:

        猜你喜欢
        • 2023-04-02
        • 2014-07-10
        • 1970-01-01
        • 1970-01-01
        • 2012-01-12
        • 2019-03-22
        • 2021-06-26
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多