Added text animations

This commit is contained in:
Ben Aultowski 2025-12-31 00:43:48 -05:00
parent 064b6c96f5
commit 2a8676cb31
8 changed files with 176 additions and 44 deletions

View file

@ -1,3 +1,10 @@
---
title: Legal notice
permalink: /docs/animation/index.html
layout: page
tags: ['docs']
---
# Hand-Drawn Animation Effects # Hand-Drawn Animation Effects
This project includes a sustainable animation system for adding hand-drawn, organic animation effects to text and UI elements throughout the site. This project includes a sustainable animation system for adding hand-drawn, organic animation effects to text and UI elements throughout the site.

View file

@ -96,6 +96,7 @@ export default async function (eleventyConfig) {
eleventyConfig.addShortcode('svg', shortcodes.svgShortcode); eleventyConfig.addShortcode('svg', shortcodes.svgShortcode);
eleventyConfig.addShortcode('image', shortcodes.imageShortcode); eleventyConfig.addShortcode('image', shortcodes.imageShortcode);
eleventyConfig.addShortcode('imageKeys', shortcodes.imageKeysShortcode); eleventyConfig.addShortcode('imageKeys', shortcodes.imageKeysShortcode);
eleventyConfig.addShortcode('animateText', shortcodes.animateText);
eleventyConfig.addShortcode('year', () => `${new Date().getFullYear()}`); eleventyConfig.addShortcode('year', () => `${new Date().getFullYear()}`);

View file

@ -16,7 +16,7 @@ const buildCss = async (inputPath, outputPaths) => {
postcssImport, postcssImport,
tailwindcss, tailwindcss,
autoprefixer, autoprefixer,
cssnano cssnano({preset: ['default', {discardUnused: false}]})
]).process(inputContent, {from: inputPath}); ]).process(inputContent, {from: inputPath});
for (const outputPath of outputPaths) { for (const outputPath of outputPaths) {

View file

@ -17,7 +17,11 @@ export const markdownLib = markdownIt({
typographer: true typographer: true
}) })
.disable('code') .disable('code')
.use(markdownItAttrs) .use(markdownItAttrs, {
leftDelimiter: '{',
rightDelimiter: '}',
allowed: ['class', 'id', 'style']
})
.use(markdownItPrism, { .use(markdownItPrism, {
defaultLanguage: 'plaintext' defaultLanguage: 'plaintext'
}) })

View file

@ -1,4 +1,19 @@
import {imageShortcode, imageKeysShortcode} from './shortcodes/image.js'; import {imageShortcode, imageKeysShortcode} from './shortcodes/image.js';
import {svgShortcode} from './shortcodes/svg.js'; import {svgShortcode} from './shortcodes/svg.js';
export default {imageShortcode, imageKeysShortcode, svgShortcode}; // Text animation shortcode - wraps each letter in a span with animation class
// Speed parameter scales animation duration: 0.5 = 2x slower, 2 = 2x faster (default: 1)
const animateText = (content, animation, speed = '1') => {
const letters = content.split('');
const letterSpans = letters
.map((letter) => {
if (letter === ' ') return ' ';
return `<span class="text-${animation}">${letter}</span>`;
})
.join('');
return letterSpans;
};
export default {imageShortcode, imageKeysShortcode, svgShortcode, animateText};

View file

@ -1,6 +1,6 @@
/* Hand-drawn animation effects for text and UI elements */ /*
SHIVER Subtle vibration and micro-rotation
/* Shiver effect - subtle shake/vibration */ */
@keyframes shiver { @keyframes shiver {
0%, 100% { 0%, 100% {
transform: translate(0, 0) rotate(0deg); transform: translate(0, 0) rotate(0deg);
@ -34,12 +34,23 @@
} }
} }
.shiver { .text-shiver {
display: inline-block; display: inline-block;
animation: shiver 0.8s ease-in-out infinite; animation: shiver 0.5s ease-in-out infinite;
} }
/* Wobble effect - gentle sway */ .text-shiver:nth-child(2n) {
animation-delay: 0.1s;
}
.text-shiver:nth-child(3n) {
animation-delay: 0.2s;
}
/*
WOBBLE Gentle sway with rotation
*/
@keyframes wobble { @keyframes wobble {
0%, 100% { 0%, 100% {
transform: rotate(0deg) translateY(0); transform: rotate(0deg) translateY(0);
@ -52,32 +63,25 @@
} }
} }
.wobble { .text-wobble {
display: inline-block; display: inline-block;
animation: wobble 2s ease-in-out infinite; animation: wobble 0.8s ease-in-out infinite;
transform-origin: center bottom; transform-origin: center bottom;
} }
/* Draw effect - simulate hand-drawing text */ .text-wobble:nth-child(2n) {
@keyframes draw-in { animation-delay: 0.3s;
from {
opacity: 0;
filter: blur(2px);
transform: translateX(-10px) rotate(-5deg);
}
to {
opacity: 1;
filter: blur(0);
transform: translateX(0) rotate(0deg);
}
} }
.draw { .text-wobble:nth-child(3n) {
display: inline-block; animation-delay: 0.6s;
animation: draw-in 0.6s cubic-bezier(0.68, -0.55, 0.27, 1.55) forwards;
} }
/* Jitter effect - erratic movement */
/*
JITTER Erratic rapid movement
*/
@keyframes jitter { @keyframes jitter {
0%, 100% { transform: translate(0, 0); } 0%, 100% { transform: translate(0, 0); }
10% { transform: translate(-2px, 1px); } 10% { transform: translate(-2px, 1px); }
@ -91,12 +95,15 @@
90% { transform: translate(-2px, -2px); } 90% { transform: translate(-2px, -2px); }
} }
.jitter { .text-jitter {
display: inline-block; display: inline-block;
animation: jitter 0.5s ease-in-out infinite; animation: jitter 0.4s ease-in-out infinite;
} }
/* Bounce effect - playful bounce */
/*
BOUNCE Playful vertical bounce
*/
@keyframes bounce { @keyframes bounce {
0%, 100% { 0%, 100% {
transform: translateY(0); transform: translateY(0);
@ -106,35 +113,111 @@
} }
} }
.bounce { .text-bounce {
display: inline-block; display: inline-block;
animation: bounce 1s ease-in-out infinite; animation: bounce 1s ease-in-out infinite;
} }
/* Stagger animations for multiple elements */
.shiver:nth-child(2n) { /*
BOBBING Independent vertical movement with staggered timing
*/
@keyframes bobbing {
0%, 100% {
transform: translateY(0);
}
50% {
transform: translateY(-8px);
}
}
.text-bob {
display: inline-block;
animation: bobbing 1.8s ease-in-out infinite;
}
.text-bob:nth-child(2n) {
animation-delay: 0.1s; animation-delay: 0.1s;
} }
.shiver:nth-child(3n) { .text-bob:nth-child(3n) {
animation-delay: 0.2s; animation-delay: 0.25s;
} }
.wobble:nth-child(2n) { .text-bob:nth-child(4n) {
animation-delay: 0.4s;
}
.text-bob:nth-child(5n) {
animation-delay: 0.55s;
}
/*
WAVE Letters move up and down in a flowing wave pattern
*/
@keyframes wave {
0% {
transform: translateY(0);
}
12.5% {
transform: translateY(-2px);
}
25% {
transform: translateY(-8px);
}
37.5% {
transform: translateY(-12px);
}
50% {
transform: translateY(-8px);
}
62.5% {
transform: translateY(-2px);
}
75% {
transform: translateY(0);
}
87.5% {
transform: translateY(2px);
}
100% {
transform: translateY(0);
}
}
.text-wave {
display: inline-block;
animation: wave 1.2s ease-in-out infinite;
}
.text-wave:nth-child(2n) {
animation-delay: 0.15s;
}
.text-wave:nth-child(3n) {
animation-delay: 0.3s; animation-delay: 0.3s;
} }
.wobble:nth-child(3n) { .text-wave:nth-child(4n) {
animation-delay: 0.45s;
}
.text-wave:nth-child(5n) {
animation-delay: 0.6s; animation-delay: 0.6s;
} }
/* Reduce motion for accessibility */
/*
ACCESSIBILITY Respect motion preferences
*/
@media (prefers-reduced-motion: reduce) { @media (prefers-reduced-motion: reduce) {
.shiver, .text-shiver,
.wobble, .text-wobble,
.draw, .text-jitter,
.jitter, .text-bounce,
.bounce { .text-bob,
.text-wave {
animation: none; animation: none;
} }
} }

View file

@ -1,6 +1,6 @@
--- ---
layout: mix layout: mix
title: "Tomorrows Bacon" title: "Tomorrow's Bacon"
project: TomorrowsBacon project: TomorrowsBacon
permalink: /mixes/tomorrowsbacon/index.html permalink: /mixes/tomorrowsbacon/index.html
go: tomorrowsbacon go: tomorrowsbacon
@ -9,6 +9,20 @@ A digital mixed CD.
Argument goes here, eventually. In the meantime, imagine that I pasted in some filler text. Argument goes here, eventually. In the meantime, imagine that I pasted in some filler text.
{% animateText "shivering", "shiver" %}
{% animateText "wobbling", "wobble" %}
{% animateText "jittering", "jitter" %}
{% animateText "bouncing", "bounce" %}
{% animateText "bobbing up and down!", "bob" %}
{% animateText "wave motion!", "wave" %}
{% animateText "slower wave", "wave", "0.5" %}
{% animateText "fast shiver", "shiver", "2" %}
{% animateText "glacial", "wobble", "0.1" %}
{% animateText "glacial", "shiver", "0.1" %}
{% set itemList = collections.mix %} {% set itemList = collections.mix %}
{% set headingLevel = "h3" %} {% set headingLevel = "h3" %}

View file

@ -28,6 +28,14 @@ const spacing = tokensToTailwind(clampGenerator(spacingTokens.items));
export default { export default {
content: ['./src/**/*.{html,js,md,njk,liquid,webc}'], content: ['./src/**/*.{html,js,md,njk,liquid,webc}'],
safelist: [
'text-shiver',
'text-wobble',
'text-jitter',
'text-bounce',
'text-bob',
'text-wave'
],
presets: [], presets: [],
theme: { theme: {
screens: { screens: {