From our sponsor: Meco is a distraction-free space for reading and discovering newsletters, separate from the inbox.
Distortion effects have become quite popular over the past two years and now many extraordinary website designs have some unique form of this intriguing trend. Today we’d like to share two demos with you that show how to use Blotter, a three.js and Underscore.js powered API for drawing artsy text effects. We used it to distort text on scroll and on mouse move.
The inspiration for this experiment comes from the project page of Bounce where you can see decorative letters being distorted on scroll.
If you enjoy this little experiment, you might also like Yannis’ Liquid Distortion Effects or Robin’s WebGL Distortion Hover Effects or Lucas’ Animated Heat Distortion Effects with WebGL.
Blotter gives us an easy to use interface for creating text effects that utilize GLSL shaders. You can use one of the many configurable effects (materials) or, if you are familiar with GLSL, implement completely new ones. Read the basics to understand how to use it and play with one of the materials to see it in action.
The main idea in our demos is to change the value of the material’s uniform
as we scroll the page. The faster the scrolling the more the value changes. Here’s a simplified example on how to achieve this:
<span data-blotter>text here</span>
const MathUtils = {
// Equation of a line.
lineEq: (y2, y1, x2, x1, currentVal) => {
var m = (y2 - y1) / (x2 - x1), b = y1 - m * x1;
return m * currentVal + b;
},
// Linear Interpolation function.
lerp: (a, b, n) => (1 - n) * a + n * b
};
// Create the blotter material.
const material = new Blotter.LiquidDistortMaterial();
// Set the default material uniform values.
material.uniforms.uSpeed.value = .5;
material.uniforms.uVolatility.value = 0;
material.uniforms.uSeed.value = 0.4;
// Create the Blotter instance.
const blotter = new Blotter(material);
// Initialize the Blotter Text on all HTML elements with data-blotter.
const blotterElems = [...document.querySelectorAll('[data-blotter]')];
blotterElems.forEach((el) => {
const text = new Blotter.Text(el.innerHTML);
blotter.addText(text);
// Now delete the html content.
el.innerHTML = '';
// The created canvas.
const scope = blotter.forText(text);
// Append it to the main element.
scope.appendTo(el);
});
// Now, change one (or more) uniform value as we scroll.
// The faster the scrolling the more the value changes.
let currentScroll = window.pageYOffset;
// The volatility is the uniform that will change.
let volatility = 0;
// It will go from 0 (not scrolling) to 0.9 (scrolling at a speed of maxscroll).
const maxscroll = 10;
const uniformValuesRange = [0,0.9];
// Using requestAnimationFrame + linear interpolation for the effect.
const render = () => {
// Current scroll position
const newScroll = window.pageYOffset;
// How much was scrolled from the last repaint.
const scrolled = Math.abs(newScroll - currentScroll);
// Get the new value of volatility.
volatility = MathUtils.lerp(volatility, Math.min(MathUtils.lineEq(uniformValuesRange[1], uniformValuesRange[0], maxscroll, 0, scrolled), 0.9), 0.05);
// Set the volatility.
material.uniforms.uVolatility.value = volatility;
// Update the current scroll.
currentScroll = newScroll;
// Repeat.
requestAnimationFrame(render);
}
requestAnimationFrame(render);
Tiny break: 📬 Want to stay up to date with frontend and trends in web design? Subscribe and get our Collective newsletter twice a tweek.
In the first demo the scroll speed determines the distortion amount:
And in the second demo, the speed of the mouse movement controls the intensity of the effect:
We hope you like this experiment and find it useful!
References and Credits
- Blotter.js
- Images from Unsplash.com
- imagesLoaded by Dave DeSandro