J'essaie de comprendre comment attraper l'événement lorsque toutes les transitions imbriquées sont terminées. Par exemple, j'ai une chaîne quand j'étais enfant, après l'avoir divisée en mots, puis chaque mot en caractères, j'essaie d'animer chaque caractère. Pour cela, j'enveloppe tous les caractères de chaque mot avec <Transition>. Mais je dois saisir l'événement lorsque tous les personnages de chaque mot sont terminés avec une animation de transition. Pour le moment, l'événement onExited se déclenche juste après le début de l'animation.

Dans le code ci-dessous, je dois trouver un moyen de définir this.state.showHeadline sur true lorsque tous les personnages ont terminé avec l'animation.

Lien vers Codesandbox

import React from "react";
import { render } from "react-dom";
import { Transition, TransitionGroup } from "react-transition-group";
import styled, { css } from "styled-components";

const Content = styled.div`
  display: flex;
`;

const Word = styled.span`
  margin-right: 0.5em;
  &:last-child {
    margin-right: 0;
  }
`;
const Char = styled.span`
  text-align: center;
  min-width: 8px;
  color: black;
  backface-visibility: visible;
  transition: opacity 4.5s, filter 2s;
  transition-timing-function: ease-in-out;
  -webkit-font-smoothing: antialiased;
  webkit-text-stroke: 0.45px;
  -webkit-text-stroke: 0.45px rgba(0, 0, 0, 0.1);

  transform: perspective(1050px) rotateY(0deg) scale(0.9);
  display: inline-block;
  opacity: 0;

  ${props =>
    props.state &&
    ((props.state === "entering" &&
      css`
        opacity: 0;
      `) ||
      (props.state === "entered" &&
        css`
          opacity: 1;
        `))}
`;

class TextWrapper extends React.Component {
  constructor() {
    super();
    this.state = {
      showTitle: false,
      showHeadline: false
    };
  }

  setState(state) {
    super.setState(state);
  }

  componentDidMount() {
    setTimeout(
      this.setState(prevState => {
        return {
          showTitle: true
        };
      }),
      1000
    );
  }

  render() {
    const content = this.props.children.split(" ").map((word, i) => {
      const chars = word.split("").map((char, i, charArray) => {
        return (
          <Transition
            in={this.state.showTitle}
            timeout={(i + 0.5) * 400}
            key={char + i}
          >
            {state => <Char state={state}>{char}</Char>}
          </Transition>
        );
      });
      return (
        <Transition key={i} timeout={0}>
          <Word>
            <TransitionGroup
              appear={true}
              component={null}
              onEntered={console.log("char")}
            >
              {chars}
            </TransitionGroup>
          </Word>
        </Transition>
      );
    });

    return (
      <React.Fragment>
        <Content>
          <TransitionGroup appear={true} component={null} onExited={null}>
            {content}
          </TransitionGroup>
        </Content>
        {this.state.showHeadline && <Content>Hello</Content>}
      </React.Fragment>
    );
  }
}

const App = () => <TextWrapper>Example Text</TextWrapper>;

const root = document.getElementById("app");
if (root) {
  render(<App />, root);
}
0
Katherine 13 mars 2019 à 23:00

2 réponses

Meilleure réponse

Vous n'avez pas besoin de redux.

Étant donné que votre CSS gère les horaires d'animation, ils seront toujours retardés par rapport au state dans lequel se trouve le Transition du personnage. Vous feriez donc plusieurs choses :

  1. Déterminez la longueur du string.
  2. Suivez tous les caractères qui sont entrés dans un état entered via leur gestionnaire d'événements onEntered. Ce gestionnaire prend une fonction de rappel qui s'ajoute à l'état keysLoaded.
  3. Comparez la longueur de l'état keysLoaded à celle de stringLength.
  4. Si les deux correspondent, cela déclenchera une fonction de rappel showHeadline.

MAIS... il faudrait quand même compenser le retard CSS transition (c'est pourquoi la fonction de rappel showHeadline est retardée de 3500ms) !

Exemple de travail :

Edit Transition Component

1
Matt Carlotta 14 mars 2019 à 06:22

Vous devez définir un compteur et un auditeur. Lorsque l'animation d'un mot se termine, comptez +1 et écoutez si le nombre est égal à la longueur des mots. Si égal, exécutez this.state.showHeadline.

0
Nana Sun 14 mars 2019 à 04:11