Как справиться с изменением высоты при использовании translate3d с реактивной пружиной?

Я пытаюсь анимировать из / в другой компонент, когда нажимаю кнопку. Я использую useTransition от react-spring. При этом анимация работает, однако мой рост смещается, когда анимация продолжается.

Я пробовал поставить разные positions на animated.div (из react-spring) и установить на нем фиксированную высоту. Но вроде ничего не работает.

// The state that keeps track on the current component
const [index, setIndex] = useState(0);

// My function that updates my state
const onClick = useCallback(() => setIndex(state => (state === 0 ? 1 : 0)), []);

// The transition I'm using
const transitions = useTransition(index, p => p, {
    from: {
        opacity: 0,
        transform: index === 0 ? "translate3d(-100%,0,0)" : "translate3d(100%,0,0)"
    },
    enter: { opacity: 1, transform: "translate3d(0%,0,0)" },
    leave: {
        opacity: 0,
        transform: index === 0 ? "translate3d(50%,0,0)" : "translate3d(-50%,0,0)"
    }
});

// My components
const pages = [
    ({ style }) => <animated.div style={style}>1</animated.div>,
    ({ style }) => <animated.div style={style}>2</animated.div>
]

// How I'm rendering out the component
{transitions.map(({ item, props, key }) => {
    const Page = pages[item];
    return <Page key={key} style={props} />;
})}

Анимация работает, но смещается высота. Я сделал небольшой кодовый ящик, который демонстрирует это здесь: https://codesandbox.io/s/dry-thunder-ydkg8

Но в моем реальном коде мой рост выглядит так: https://youtu.be/7cGLOK7fCco


person Martin Nordström    schedule 29.05.2019    source источник


Ответы (1)


Вам нужно использовать position:absolute на двух элементах, чтобы избежать этого сдвига (и добавить position:relative на один из родительских контейнеров) - (см. обновленные коды и окно):

const pages = [
    ({ style }) => (
      <animated.div
        style={{
          ...style,
          position: "absolute",
          top: "0",
          backgroundColor: "red"
        }}
      >
        First page
      </animated.div>
    ),
    ({ style }) => (
      <animated.div
        style={{
          ...style,
          position: "absolute",
          top: "0",
          backgroundColor: "blue"
        }}
      >
        Second page
      </animated.div>
    )
  ];

person Gaël S    schedule 29.05.2019