Wawa Sensei logo
LoginEnroll now

Transiciones con shaders

Starter pack

En esta lecci贸n aprenderemos a crear transiciones usando shaders.

El primer efecto que crearemos es un efecto de transici贸n de pantalla:

Tenemos control total sobre el efecto de transici贸n, podemos cambiar la duraci贸n, la funci贸n de easing, y el shader en s铆.

El segundo efecto que crearemos es un efecto de transici贸n de modelo:

Cuando se desvanece, el modelo se disuelve y los colores se desvanecen en blanco, lo opuesto ocurre al aparecer.

Paquete inicial

Aqu铆 est谩n todos los modelos 3D que usaremos en esta lecci贸n por Ergoni y con licencia de Creative Commons Attribution:

El paquete inicial utiliza los siguientes paquetes:

Las dos fuentes utilizadas son Kanit y Rubik Doodle Shadow, ambas de Google Fonts.

Si茅ntete libre de ajustar cualquier componente a tus preferencias.

Puedes ajustar los colores jugando con los controles de Leva en la esquina superior derecha. Una vez que encuentres los colores que te gusten, a帽ade la propiedad hidden al componente Leva en App.jsx:

// ...

function App() {
  // ...
  return (
    <>
      <Leva hidden />
      {/* ... */}
    </>
  );
}

// ...

Transici贸n de pantalla

Empecemos creando nuestro efecto de transici贸n de pantalla. Vamos a crear un componente llamado ScreenTransition que manejar谩 el efecto de transici贸n.

Vamos a crear un nuevo archivo llamado ScreenTransition.jsx en la carpeta components:

export const ScreenTransition = ({ transition, color }) => {
  return (
    <mesh>
      <planeGeometry args={[2, 2]} />
      <meshBasicMaterial color={color} />
    </mesh>
  );
};

En este componente, estamos creando un plano con un color que cubrir谩 toda la pantalla. Utilizaremos este plano para hacer la transici贸n entre pantallas.

Nuestro componente toma dos props:

  • transition: un booleano para saber si el componente debe mostrar el efecto de transici贸n
  • color: el color principal del efecto de transici贸n

A帽adamos el componente ScreenTransition a App.jsx:

// ...
import { ScreenTransition } from "./components/ScreenTransition";

function App() {
  // ...
  return (
    <>
      {/* ... */}
      <Canvas camera={{ position: [0, 1.8, 5], fov: 42 }}>
        <color attach="background" args={[backgroundColor]} />
        <fog attach="fog" args={[backgroundColor, 5, 12]} />
        <ScreenTransition transition color="#a5b4fc" />
        <Suspense>
          <Experience />
        </Suspense>
      </Canvas>
    </>
  );
}

export default App;

Por ahora, forzamos que se muestre el efecto de transici贸n pasando true a la prop transition. A帽adiremos la l贸gica para controlar el efecto de transici贸n m谩s tarde.

Ajusta el color a tu gusto. Si lo cambias, aseg煤rate de actualizar el color en el archivo index.css para evitar un destello de color cuando cargue la p谩gina web:

// ...

html {
  background-color: #a5b4fc;
}

Plane in middle of the scene

El plano est谩 en el medio de la escena.

Plano a pantalla completa

Queremos que nuestro plano cubra toda la pantalla. Podr铆amos usar las dimensiones del viewport y hacer que mire hacia la c谩mara, pero tambi茅n queremos que est茅 encima de todo.

Para lograr esto, Drei proporciona un componente Hud que renderizar谩 a sus hijos encima de todo. Podemos agregar una c谩mara fija al componente Hud para asegurarnos de que est茅 perfectamente alineada con nuestro plano:

import { Hud, OrthographicCamera } from "@react-three/drei";

export const ScreenTransition = ({ transition, color }) => {
  return (
    <Hud>
      <OrthographicCamera
        makeDefault
        top={1}
        right={1}
        bottom={-1}
        left={-1}
        near={0}
        far={1}
      />
      <mesh>
        <planeGeometry args={[2, 2]} />
        <meshBasicMaterial color={color} />
      </mesh>
    </Hud>
  );
};

Usamos una OrthographicCamera para cubrir f谩cilmente toda la pantalla, independientemente de la distancia entre la c谩mara y el plano.

Plane covering the entire screen

El plano ahora cubre toda la pantalla.

L贸gica de transici贸n

Una 煤ltima cosa antes de crear nuestro shader personalizado, vamos a definir un estado de transici贸n en UI.jsx:

// ...
import { atom } from "jotai";

export const transitionAtom = atom(true);
// ...

Establecemos el valor inicial en true para comenzar con un efecto de desvanecimiento despu茅s de que el sitio web se cargue.

Usaremos este estado para controlar el efecto de transici贸n.

A煤n en UI.jsx, definiremos dos constantes para controlar la duraci贸n y el retraso del efecto de transici贸n:

// ...
export const TRANSITION_DELAY = 0.8;
export const TRANSITION_DURATION = 3.2;
// ...

Ahora, reemplazaremos la llamada a la funci贸n setScreen con una nueva que manejar谩 el efecto de transici贸n:

// ...
import { useAtom } from "jotai";
import { useRef } from "react";
// ...

export const UI = () => {
  // ...
  const [transition, setTransition] = useAtom(transitionAtom);
  const timeout = useRef();

  // ...
  const transitionToScreen = (newScreen) => {
    setTransition(true);
    clearTimeout(timeout.current);
    timeout.current = setTimeout(() => {
      setScreen(newScreen);
      setTransition(false);
    }, TRANSITION_DURATION * 1000 + TRANSITION_DELAY * 1000);
  };
  // ...
};

En lugar de establecer directamente la nueva pantalla, configuramos el estado de transici贸n a true y usamos un setTimeout para establecer la nueva pantalla despu茅s de que se complete el efecto de transici贸n (la duraci贸n del efecto de transici贸n m谩s el retraso).

Ahora nuestra funci贸n est谩 lista, busca las llamadas a setScreen en el componente UI y reempl谩zalas con transitionToScreen.

De home a menu:

<motion.button
  onClick={() => transitionToScreen("menu")}
  // ...
>

Y de menu a home:

<motion.button
onClick={() => transitionToScreen("home")}
// ...
>

End of lesson preview

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