Morphing Text Effect With SVG And JavaScript

Category: Animation , Javascript , Text | June 23, 2021
Author: Valgo
Views Total: 115 views
Official Page: Go to website
Last Update: June 23, 2021
License: MIT

Preview:

Morphing Text Effect With SVG And JavaScript

Description:

This project utilizes JavaScript SVG filters to create a “Morphing Text” effect.

It layers 2 text elements on top of each other and blurs them depending on which text element should be more visible.

Once the blurring is applied, both texts are fed through a threshold filter together, which produces the “gooey” effect.

See It In Action:

See the Pen
Text Morph
by Valgo (@Valgo)
on CodePen.

How to use it:

1. Create two text containers on the page.

<div id="container">
  <span id="text1"></span>
  <span id="text2"></span>
</div>

2. Create an SVG filter used to create the morphing effect.

<svg id="filters">
  <defs>
    <filter id="threshold">
      <!-- Basically just a threshold effect - pixels with a high enough opacity are set to full opacity, and all other pixels are set to completely transparent. -->
      <feColorMatrix in="SourceGraphic"
          type="matrix"
          values="1 0 0 0 0
                  0 1 0 0 0
                  0 0 1 0 0
                  0 0 0 255 -140" />
    </filter>
  </defs>
</svg>

3. The core stylesheet.

#container {
  filter: url(#threshold) blur(0.6px);
}

4. The main JavaScript to enable the text morphing effect. Don’t forget to replace the text that you want to morph between:

const elts = {
  text1: document.getElementById("text1"),
  text2: document.getElementById("text2") 
};
// The strings to morph between. You can change these to anything you want!
const texts = [
      "JavaScript",
      "CSS",
      "HTML",
      "jQuery",
      "Angular",
      "React",
      "Vue"
];
// Controls the speed of morphing.
const morphTime = 1;
const cooldownTime = 0.25;
let textIndex = texts.length - 1;
let time = new Date();
let morph = 0;
let cooldown = cooldownTime;
elts.text1.textContent = texts[textIndex % texts.length];
elts.text2.textContent = texts[(textIndex + 1) % texts.length];
function doMorph() {
  morph -= cooldown;
  cooldown = 0;
  let fraction = morph / morphTime;
  if (fraction > 1) {
    cooldown = cooldownTime;
    fraction = 1;
  }
  setMorph(fraction);
}
// A lot of the magic happens here, this is what applies the blur filter to the text.
function setMorph(fraction) {
  // fraction = Math.cos(fraction * Math.PI) / -2 + .5;
  elts.text2.style.filter = `blur(${Math.min(8 / fraction - 8, 100)}px)`;
  elts.text2.style.opacity = `${Math.pow(fraction, 0.4) * 100}%`;
  fraction = 1 - fraction;
  elts.text1.style.filter = `blur(${Math.min(8 / fraction - 8, 100)}px)`;
  elts.text1.style.opacity = `${Math.pow(fraction, 0.4) * 100}%`;
  elts.text1.textContent = texts[textIndex % texts.length];
  elts.text2.textContent = texts[(textIndex + 1) % texts.length];
}
function doCooldown() {
  morph = 0;
  elts.text2.style.filter = "";
  elts.text2.style.opacity = "100%";
  elts.text1.style.filter = "";
  elts.text1.style.opacity = "0%";
}
// Animation loop, which is called every frame.
function animate() {
  requestAnimationFrame(animate);
  let newTime = new Date();
  let shouldIncrementIndex = cooldown > 0;
  let dt = (newTime - time) / 1000;
  time = newTime;
  cooldown -= dt;
  if (cooldown <= 0) {
    if (shouldIncrementIndex) {
      textIndex++;
    }
    doMorph();
  } else {
    doCooldown();
  }
}
// Start the animation.
animate();

You Might Be Interested In:


Leave a Reply