Wawa Sensei logo

Animações

Starter pack

Animações são essenciais para dar vida à sua cena 3D. Elas podem ser acionadas por interações do usuário, baseadas em scroll ou tempo, e aplicadas a objetos 3D, luzes e câmeras.

Dominar as animações é uma habilidade chave para criar experiências imersivas. Quanto mais técnicas você conhece, mais você pode expressar sua criatividade.

Nota: As animações de modelos 3D são cobertas no capítulo de modelos.

Lerp

Lerp é uma função matemática que interpola entre dois valores. É útil para animar um valor de um ponto a outro.

const value = THREE.MathUtils.lerp(start, end, t);

O primeiro parâmetro é o valor inicial, o segundo parâmetro é o valor final e o terceiro parâmetro é o fator de interpolação entre 0 e 1.

Quanto mais próximo o fator de interpolação estiver de 0, mais lenta será a animação. Quanto mais próximo de 1, mais rapidamente a animação atingirá o valor final ou alvo.

Vamos experimentar isso no componente AnimatedBox do pacote inicial.

O componente possui um array boxPositions que contém as posições da caixa em diferentes momentos. Vamos adicionar um hook useFrame para atualizar a posição da caixa com base no tempo:

import { RoundedBox } from "@react-three/drei";
import { useRef } from "react";

export const AnimatedBox = ({ boxPositions, ...props }) => {
  const box = useRef();

  useFrame(({ clock }) => {
    const seconds = parseInt(clock.getElapsedTime());
    const targetPosition = boxPositions[seconds % boxPositions.length];

    box.current.position.x = targetPosition.x;
    box.current.position.y = targetPosition.y;
    box.current.position.z = targetPosition.z;
  });
  // ...
};

Aqui nossa caixa não está animada. Ela se teletransporta de uma posição para outra. Vamos usar a função lerp para animá-la:

import * as THREE from "three";
// ...

export const AnimatedBox = ({ boxPositions, ...props }) => {
  const box = useRef();

  useFrame(({ clock }) => {
    const seconds = parseInt(clock.getElapsedTime());
    const targetPosition = boxPositions[seconds % boxPositions.length];
    box.current.position.x = THREE.MathUtils.lerp(
      box.current.position.x,
      targetPosition.x,
      0.05
    );
    box.current.position.y = THREE.MathUtils.lerp(
      box.current.position.y,
      targetPosition.y,
      0.05
    );
    box.current.position.z = THREE.MathUtils.lerp(
      box.current.position.z,
      targetPosition.z,
      0.05
    );
  });
  // ...
};

A caixa agora está animada. Ela se move suavemente de uma posição para outra.

A classe Vector3 tem um método lerp que pode ser usado em vez da função THREE.MathUtils.lerp:

// box.current.position.x = THREE.MathUtils.lerp(
//   box.current.position.x,
//   targetPosition.x,
//   0.05
// );
// box.current.position.y = THREE.MathUtils.lerp(
//   box.current.position.y,
//   targetPosition.y,
//   0.05
// );
// box.current.position.z = THREE.MathUtils.lerp(
//   box.current.position.z,
//   targetPosition.z,
//   0.05
// );
box.current.position.lerp(targetPosition, 0.05);

Muitas linhas economizadas para o mesmo resultado!

Não hesite em brincar com o tempo e interpolar outras propriedades como a rotação ou a escala para experimentar efeitos diferentes.

Float

Float é um componente wrapper da biblioteca Drei que simplesmente dá a impressão de que um objeto está flutuando.

Ele contém as seguintes props:

  • speed: Velocidade da animação, padrão é 1
  • rotationIntensity: Intensidade da rotação XYZ, padrão é 1
  • floatIntensity: Intensidade da flutuação para cima/baixo, funciona como um multiplicador com o floatingRange, padrão é 1
  • floatingRange: Intervalo de valores no eixo y dentro do qual o objeto irá flutuar, padrão é [-0.1,0.1]

Vamos fazer nosso Duck flutuar em Experience.jsx:

End of lesson preview

To get access to the entire lesson, you need to purchase the course.