Author: | Valgo |
---|---|
Views Total: | 1,932 views |
Official Page: | Go to website |
Last Update: | June 23, 2021 |
License: | MIT |
Preview:

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();