Exploring a 3D Textual content Distortion Impact With React Three Fiber

[ad_1]

ring

Immediately we’ll check out how you can create an exquisite animation in React Three Fiber. The concept is to point out a 3D scene within the background that appears like a distorted glassy view of a textual content ring, consistently rotating round its personal axis. It’s an exquisite design ingredient that might be used as an animated background. The animation isn’t very complicated, good for these fascinated with getting began with 3D animation and extra.

It is a React particular tutorial so make sure to have an preliminary React app arrange in order that we are able to begin.

First we might want to set up React Three Fiber:

npm set up three @react-three/fiber

After that we are going to put together the canvas for rendering our 3D scene.

We first import the canvas from @react-three/fiber, model the primary ingredient to be 100% viewport width and peak and use the imported Canvas part. We’ll additionally model it to have a black background.

import { Canvas } from "@react-three/fiber";

export default operate App() {
  return (
    <principal className="h-screen w-screen">
      <Canvas className="bg-black">

      </Canvas>
    </principal>
  );
}

The subsequent step is to arrange our 3D part that can be rendered contained in the Canvas which we’ll name ring as a result of we’ll be wrapping the textual content within the type of a hoop. The way in which we are able to think about that is as if we took our textual content and wrapped it round a bottle which might be forming this so referred to as “TextRing”.

interface Props {
  radius: quantity;
  peak: quantity;
  segments: quantity;
}

export default operate Ring({ radius, peak, segments }: Props) {
  return (
    <mesh>
      <cylinderGeometry args={[radius, radius, height, segments]} />
      <meshBasicMaterial />
    </mesh>
  );
}

After you will have written the part the one remaining factor left to do is add it to the primary scene in our Canvas:

import { Canvas } from "@react-three/fiber";
import Ring from "./ring";

export default operate Scene() {
  return (
    <Canvas className="bg-black">
      <Ring radius={2} peak={4} segments={32} />
    </Canvas>
  );
}

After this you ought to be seeing this in your display:

image

Within the subsequent step we should embrace our textual content within the scene and in an effort to to that we are going to set up one other bundle referred to as @react-three/drei that has a numerous superior issues. On this case we use the Textual content part.

npm set up @react-three/drei

After we put in our bundle we’ve got to regulate our part in an effort to present our textual content and wrap it round our cylinder:

import { Textual content } from "@react-three/drei";

interface Props {
  textual content: string;
  radius: quantity;
  peak: quantity;
  segments: quantity;
}

export default operate Ring({ textual content, radius, peak, segments }: Props) {
  // Calculate positions for textual content
  const textPositions: { x: quantity; z: quantity }[] = [];
  const angleStep = (2 * Math.PI) / textual content.size;
  for (let i = 0; i < textual content.size; i++) {
    const angle = i * angleStep;
    const x = radius * Math.cos(angle);
    const z = radius * Math.sin(angle);
    textPositions.push({ x, z });
  }

  return (
    <group>
      <mesh>
        <cylinderGeometry args={[radius, radius, height, segments]} />
        <meshBasicMaterial />
      </mesh>
      {textual content.cut up("").map((char: string, index: quantity) => (
        <Textual content
          key={index}
          place={[textPositions[index].x, 0, textPositions[index].z]}
          rotation={[0, -angleStep * index + Math.PI / 2, 0]}
          fontSize={0.3}
          lineHeight={1}
          letterSpacing={0.02}
          shade="white"
          textAlign="middle"
        >
          {char}
        </Textual content>
      ))}
    </group>
  );
}

So, there may be quite a lot of issues occurring right here, however to elucidate it in primary terminology, we take every character and more and more place it round in a round place. We use the radius that we used for the cylinder to place all of the letters.

We move any textual content into the Ring part after this, after which it will likely be neatly wrapper across the cylinder like this:

export default operate Scene() {
  return (
    <Canvas className="bg-black">
      <Ring
        radius={2}
        peak={4}
        segments={32}
        textual content="X X X X X X X X X X X X X X X X X X X X X X X X X X X X "
      />
    </Canvas>
  );
}
image 1

To begin animating issues, we’ll merely take the group and rotate it alongside its x,y,z axis. For that we are going to use the useFrame hook from R3F and we’ll entry the ingredient through the useRef that we are going to hyperlink to the group ingredient.

import { useRef } from "react";
import { useFrame } from "@react-three/fiber";
import { Textual content } from "@react-three/drei";

interface Props {
  textual content: string;
  radius: quantity;
  peak: quantity;
  segments: quantity;
}

export default operate Ring({ textual content, radius, peak, segments }: Props) {
  const ref = useRef<any>();

  // Rotate the textual content
  useFrame(() => {
    ref.present.rotation.y += 0.01;
    ref.present.rotation.x += 0.01;
    ref.present.rotation.z += 0.01;
  });

  // Calculate positions for textual content
  const textPositions: { x: quantity; z: quantity }[] = [];
  const angleStep = (2 * Math.PI) / textual content.size;
  for (let i = 0; i < textual content.size; i++) {
    const angle = i * angleStep;
    const x = radius * Math.cos(angle);
    const z = radius * Math.sin(angle);
    textPositions.push({ x, z });
  }
  return (
    <group ref={ref}>
      <mesh>
        <cylinderGeometry args={[radius, radius, height, segments]} />
        <meshBasicMaterial />
      </mesh>
      {textual content.cut up("").map((char: string, index: quantity) => (
        <Textual content
          key={index}
          place={[textPositions[index].x, 0, textPositions[index].z]}
          rotation={[0, -angleStep * index + Math.PI / 2, 0]}
          fontSize={0.3}
          lineHeight={1}
          letterSpacing={0.02}
          shade="white"
          textAlign="middle"
        >
          {char}
        </Textual content>
      ))}
    </group>
  );
}

The one remaining step left to do is to barely distort the ingredient a bit and make it glass-like trying. Fortunately, drei has a cloth that helps us with that referred to as MeshTransmissionMaterial:

import { useRef } from "react";
import { useFrame } from "@react-three/fiber";
import { MeshTransmissionMaterial, Textual content } from "@react-three/drei";

interface Props {
  textual content: string;
  radius: quantity;
  peak: quantity;
  segments: quantity;
}

export default operate Ring({ textual content, radius, peak, segments }: Props) {
  const ref = useRef<any>();

  // Rotate the textual content
  useFrame(() => {
    ref.present.rotation.y += 0.01;
    ref.present.rotation.x += 0.01;
    ref.present.rotation.z += 0.01;
  });

  // Calculate positions for textual content
  const textPositions: { x: quantity; z: quantity }[] = [];
  const angleStep = (2 * Math.PI) / textual content.size;
  for (let i = 0; i < textual content.size; i++) {
    const angle = i * angleStep;
    const x = radius * Math.cos(angle);
    const z = radius * Math.sin(angle);
    textPositions.push({ x, z });
  }

  return (
    <group ref={ref}>
      <mesh>
        <cylinderGeometry args={[radius, radius, height, segments]} />
        <MeshTransmissionMaterial
          bottom
          backsideThickness={5}
          thickness={2}
        />
      </mesh>
      {textual content.cut up("").map((char: string, index: quantity) => (
        <Textual content
          key={index}
          place={[textPositions[index].x, 0, textPositions[index].z]}
          rotation={[0, -angleStep * index + Math.PI / 2, 0]}
          fontSize={0.3}
          lineHeight={1}
          letterSpacing={0.02}
          shade="white"
          textAlign="middle"
        >
          {char}
        </Textual content>
      ))}
    </group>
  );
}

And with that we’ve got our stunning rotating glassy textual content ring:

I hope you loved this tutorial!

I’m open for collaborations and tasks, so drop me a line in the event you’d wish to work with me!

Design Finds: Detail Hovers on Images

[ad_2]

Add a Comment