Falling Text Animation JavaScript

Falling Text Animation JavaScript
Project: Falling Words
Author: Gayane Gasparyan
Edit Online: View on CodePen
License: MIT

The following code implements a falling text animation using JavaScript. It splits the text content of a specified HTML element into individual words and highlights certain words based on specific criteria. It then creates a canvas using the Matter.js physics engine, where the words and other elements are rendered.

The words fall from the top of the canvas and interact with the boundaries of the canvas. The animation creates an engaging visual effect that can be used to enhance the user experience on websites or applications.

How to Create Falling Text Animation

First of all, create a div element with a class name “text” and place your text inside it.

<main>
<div class="text">software developer with over 9 years of experience, I have developed a strong foundation in crafting innovative and efficient technology solutions. My passion for technology and entrepreneurship led me to co-found Mythrill, where I currently serve as the CTO. I am proud to be recognized as one of the "30under30" Armenians in Tech and am constantly driven to push boundaries and make a positive impact in the industry. When I'm not coding, I enjoy exploring my creative side through art, music, and nature</div>
</main>

Use the following CSS styles for the falling text. You can set the custom background and text color according to your needs.

@import url('https://fonts.googleapis.com/css2?family=Inconsolata:wght@200;300;400;900&display=swap');

body{
  margin: 0;
  padding: 0;
  background: #000fff !important;
  color: transparent;
  font-family: 'Inconsolata', monospace;
  width: 100vw;
}
* {
  user-select: none;
}
.word {
  position: absolute;
  cursor: grab;
  font-size: 30px;
  color: #ffeb3b;
}
.word.highlighted {
  font-weight: bold;
  color: black;
}

a {
  text-decoration: none;
  color: black;
  display: block;
  padding: 1rem;
}

Now, load the Matter JS by adding the following CDN link before closing the body tag:

<script src='https://cdnjs.cloudflare.com/ajax/libs/matter-js/0.19.0/matter.min.js'></script>

Finally, add the following JavaScript code between the <script> and </script> tag before closing the body element to initialize the text falling animation.

const splitWords = () => {
  const textNode = document.querySelector(".text");
  const text = textNode.textContent;
  const newDomElements = text.split(" ").map((text) => {
    const highlighted =
      text.startsWith(`"30under30"`) ||
      text.startsWith(`CTO`) ||
      text.startsWith(`Mythrill`);
    return `<span class="word ${
      highlighted ? "highlighted" : null
    }">${text}</span>`;
  });
  textNode.innerHTML = newDomElements.join("");
};

const renderCanvas = () => {
  const Engine = Matter.Engine;
  const Render = Matter.Render;
  const World = Matter.World;
  const Bodies = Matter.Bodies;
  const Runner = Matter.Runner;
  const params = {
    isStatic: true,
    render: {
      fillStyle: "transparent"
    }
  };
  const canvasSize = {
    width: window.innerWidth,
    height: window.innerHeight
  };
  const engine = Engine.create({});

  const render = Render.create({
    element: document.body,
    engine: engine,
    options: {
      ...canvasSize,
      background: "transparent",
      wireframes: false
    }
  });
  const floor = Bodies.rectangle(
    canvasSize.width / 2,
    canvasSize.height,
    canvasSize.width,
    50,
    params
  );
  const wall1 = Bodies.rectangle(
    0,
    canvasSize.height / 2,
    50,
    canvasSize.height,
    params
  );
  const wall2 = Bodies.rectangle(
    canvasSize.width,
    canvasSize.height / 2,
    50,
    canvasSize.height,
    params
  );
  const top = Bodies.rectangle(
    canvasSize.width / 2,
    0,
    canvasSize.width,
    50,
    params
  );
  const wordElements = document.querySelectorAll(".word");
  const wordBodies = [...wordElements].map((elemRef) => {
    const width = elemRef.offsetWidth;
    const height = elemRef.offsetHeight;

    return {
      body: Matter.Bodies.rectangle(canvasSize.width / 2, 0, width, height, {
        render: {
          fillStyle: "transparent"
        }
      }),
      elem: elemRef,
      render() {
        const { x, y } = this.body.position;
        this.elem.style.top = `${y - 20}px`;
        this.elem.style.left = `${x - width / 2}px`;
        this.elem.style.transform = `rotate(${this.body.angle}rad)`;
      }
    };
  });

  const mouse = Matter.Mouse.create(document.body);
  const mouseConstraint = Matter.MouseConstraint.create(engine, {
    mouse,
    constraint: {
      stiffness: 0.2,
      render: {
        visible: false
      }
    }
  });
  mouse.element.removeEventListener("mousewheel", mouse.mousewheel);
  mouse.element.removeEventListener("DOMMouseScroll", mouse.mousewheel);

  World.add(engine.world, [
    floor,
    ...wordBodies.map((box) => box.body),
    wall1,
    wall2,
    top,
    mouseConstraint
  ]);
  render.mouse = mouse;
  Runner.run(engine);
  Render.run(render);

  (function rerender() {
    wordBodies.forEach((element) => {
      element.render();
    });
    Matter.Engine.update(engine);
    requestAnimationFrame(rerender);
  })();
};

window.addEventListener("DOMContentLoaded", (event) => {
  splitWords();
  renderCanvas();
});

That’s all! hopefully, you have successfully created falling text animation. If you have any questions or suggestions, feel free to comment below.

Leave a Comment

Comments

No comments yet. Why don’t you start the discussion?

Leave a Reply