Skip to content

Commit e836ae0

Browse files
committed
feat: Add parameterization and color-morphing to wave animations
Enable full customization of the wave effect in bubbles animation with new parameters and add a mesmerizing color-morphing gradient option. New Parameters: 1. wave_speed (default: 2) - Controls wave cycle duration in seconds - Lower values = faster waves - Range: 0.5 to 5 seconds recommended 2. wave_amplitude (default: 3) - Controls vertical movement height in pixels - Higher values = bigger waves - Range: 1 to 10 pixels recommended 3. wave_delay (default: 0.05) - Controls delay between each character in seconds - Determines how fast wave travels horizontally - Range: 0.01 to 0.2 seconds recommended 4. color_morph (default: false) - Enables color morphing gradient effect - Letters cycle through theme colors smoothly - Animation cycle is 3x the wave_speed Color Morphing Implementation: - Animates through titleColor → iconColor → textColor → iconColor → titleColor - Uses CSS fill animation for smooth transitions - Combines with wave motion for dual-animation effect - Automatically uses theme colors for perfect integration Technical Details: - Parameters passed through API → renderRepoCard → getAnimationStyle - wrapTextInWave updated to conditionally add wave-char-morph class - CSS keyframes dynamically generated with user parameters - Proper type conversion (parseFloat) for numeric params in API - Maintains backward compatibility with default values Example Usage: - Fast big waves: wave_speed=1&wave_amplitude=6&wave_delay=0.03 - Slow gentle: wave_speed=3&wave_amplitude=2&wave_delay=0.08 - Color morph: color_morph=true (combines with any wave params) Documentation: - Added Wave Customization Parameters section - New usage examples showing different combinations - Parameter reference with ranges and recommendations - Examples of fast, slow, and color-morphing variations
1 parent 63e9583 commit e836ae0

3 files changed

Lines changed: 103 additions & 10 deletions

File tree

ANIMATION_EXAMPLES.md

Lines changed: 54 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -76,15 +76,29 @@ animation_style=bubbles
7676
- 2 glowing jellyfish with wavy tentacles drifting left to right
7777
- 2 starfish slowly rotating and drifting right to left
7878
- **🌊 Horizontal wave text effect**: Letters ripple like a wave traveling across the text
79-
- Each character animates individually with a staggered delay (0.05s per letter)
79+
- Each character animates individually with a staggered delay
8080
- Creates a smooth left-to-right wave motion across the title
81-
- 2-second wave cycle with 3px vertical movement
82-
- Like text floating and undulating in water
81+
- Fully customizable wave parameters (see below)
82+
- Optional color-morphing gradient effect
8383
- Jellyfish appear every ~12 seconds with gentle pulsing glow
8484
- Starfish drift across every ~15 seconds with slow rotation
8585
- All creatures layered behind text for depth
8686
- Perfect for: Calm, steady progress projects, marine/ocean themes, underwater aesthetics
8787

88+
**Wave Customization Parameters:**
89+
- `wave_speed` - Wave cycle duration in seconds (default: `2`)
90+
- Lower = faster wave, Higher = slower wave
91+
- Example: `wave_speed=1.5` for faster waves
92+
- `wave_amplitude` - Vertical movement in pixels (default: `3`)
93+
- How high each letter bounces
94+
- Example: `wave_amplitude=5` for bigger waves
95+
- `wave_delay` - Delay between each character in seconds (default: `0.05`)
96+
- Controls how quickly wave travels horizontally
97+
- Example: `wave_delay=0.08` for slower wave travel
98+
- `color_morph` - Enable color morphing gradient (default: `false`)
99+
- Letters cycle through theme colors
100+
- Example: `color_morph=true`
101+
88102
### 2. **embers** - Burning Particles 🔥
89103
Glowing particles pulse and float like hot embers.
90104
```
@@ -148,6 +162,21 @@ animation_style=sparks
148162
![Repo Card](https://your-domain.vercel.app/api/pin?username=hesreallyhim&repo=your-repo&theme=robot_blue&animation_style=sparks&show_owner=true&all_stats=true)
149163
```
150164

165+
### Custom Wave Effect (Fast & Big)
166+
```markdown
167+
![Repo Card](https://your-domain.vercel.app/api/pin?username=hesreallyhim&repo=your-repo&theme=mad_scientist&animation_style=bubbles&wave_speed=1&wave_amplitude=6&wave_delay=0.03)
168+
```
169+
170+
### Color Morphing Wave
171+
```markdown
172+
![Repo Card](https://your-domain.vercel.app/api/pin?username=hesreallyhim&repo=your-repo&theme=electric_laboratory&animation_style=bubbles&color_morph=true)
173+
```
174+
175+
### Slow Gentle Wave
176+
```markdown
177+
![Repo Card](https://your-domain.vercel.app/api/pin?username=hesreallyhim&repo=your-repo&theme=robot_blue&animation_style=bubbles&wave_speed=3&wave_amplitude=2&wave_delay=0.08)
178+
```
179+
151180
### Disable Animations (for static images)
152181
```markdown
153182
![Repo Card](https://your-domain.vercel.app/api/pin?username=hesreallyhim&repo=your-repo&theme=electric_laboratory&disable_animations=true)
@@ -202,6 +231,28 @@ Dark background with pulsing radiant center - excellent for core libraries.
202231
- Options: `true`, `false`
203232
- Default: `false`
204233

234+
### Wave Customization Parameters (bubbles only)
235+
- `wave_speed` - Duration of one wave cycle in seconds
236+
- Range: `0.5` to `5` (recommended)
237+
- Default: `2`
238+
- Example: `wave_speed=1.5` (faster)
239+
240+
- `wave_amplitude` - Vertical movement height in pixels
241+
- Range: `1` to `10` (recommended)
242+
- Default: `3`
243+
- Example: `wave_amplitude=5` (bigger waves)
244+
245+
- `wave_delay` - Delay between each character in seconds
246+
- Range: `0.01` to `0.2` (recommended)
247+
- Default: `0.05`
248+
- Example: `wave_delay=0.08` (slower horizontal travel)
249+
250+
- `color_morph` - Enable color morphing gradient effect
251+
- Options: `true`, `false`
252+
- Default: `false`
253+
- Cycles through title, icon, and text colors
254+
- Example: `color_morph=true`
255+
205256
### All Compatible Parameters
206257
You can combine animations with all existing repo card parameters:
207258
- `theme` - Choose from 65+ themes (including 5 new cybernetic ones)

api/pin.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,10 @@ export default async (req, res) => {
4444
age_metric,
4545
animation_style,
4646
disable_animations,
47+
wave_speed,
48+
wave_amplitude,
49+
wave_delay,
50+
color_morph,
4751
} = req.query;
4852

4953
res.setHeader("Content-Type", "image/svg+xml");
@@ -120,6 +124,10 @@ export default async (req, res) => {
120124
age_metric: age_metric || "first",
121125
animation_style: animation_style || "none",
122126
disable_animations: parseBoolean(disable_animations),
127+
wave_speed: wave_speed ? parseFloat(wave_speed) : 2,
128+
wave_amplitude: wave_amplitude ? parseFloat(wave_amplitude) : 3,
129+
wave_delay: wave_delay ? parseFloat(wave_delay) : 0.05,
130+
color_morph: parseBoolean(color_morph),
123131
}),
124132
);
125133
} catch (err) {

src/cards/repo.js

Lines changed: 41 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,15 +25,22 @@ const DESCRIPTION_MAX_LINES = 3;
2525
* @param {string} text The text to wrap.
2626
* @param {number} baseDelay Base delay in seconds before wave starts.
2727
* @param {number} delayPerChar Delay in seconds between each character.
28+
* @param {boolean} colorMorph Whether to enable color morphing effect.
2829
* @returns {string} SVG tspan elements with wave animation.
2930
*/
30-
const wrapTextInWave = (text, baseDelay = 0, delayPerChar = 0.05) => {
31+
const wrapTextInWave = (
32+
text,
33+
baseDelay = 0,
34+
delayPerChar = 0.05,
35+
colorMorph = false,
36+
) => {
3137
return Array.from(text)
3238
.map((char, i) => {
3339
const delay = baseDelay + i * delayPerChar;
3440
// Preserve spaces
3541
const displayChar = char === " " ? "\u00A0" : char;
36-
return `<tspan class="wave-char" style="animation-delay: ${delay}s">${displayChar}</tspan>`;
42+
const morphClass = colorMorph ? " wave-char-morph" : "";
43+
return `<tspan class="wave-char${morphClass}" style="animation-delay: ${delay}s">${displayChar}</tspan>`;
3744
})
3845
.join("");
3946
};
@@ -45,15 +52,21 @@ const wrapTextInWave = (text, baseDelay = 0, delayPerChar = 0.05) => {
4552
* @param {object} colors Card colors for theming animations.
4653
* @param {number} width Card width.
4754
* @param {number} height Card height.
55+
* @param {object} waveParams Wave animation parameters.
4856
* @returns {{css: string, svg: string}} Animation CSS and SVG elements.
4957
*/
50-
const getAnimationStyle = (style, colors, width, height) => {
58+
const getAnimationStyle = (style, colors, width, height, waveParams = {}) => {
5159
if (!style || style === "none") {
5260
return { css: "", svg: "" };
5361
}
5462

5563
const iconColor = colors.iconColor || "38bdf8";
5664
const titleColor = colors.titleColor || "00d9ff";
65+
const textColor = colors.textColor || "434d58";
66+
67+
// Wave parameters with defaults
68+
const waveSpeed = waveParams.speed || 2; // seconds
69+
const waveAmplitude = waveParams.amplitude || 3; // pixels
5770

5871
switch (style) {
5972
case "bubbles": {
@@ -191,7 +204,14 @@ const getAnimationStyle = (style, colors, width, height) => {
191204
}
192205
@keyframes letterWave {
193206
0%, 100% { transform: translateY(0px); }
194-
50% { transform: translateY(-3px); }
207+
50% { transform: translateY(-${waveAmplitude}px); }
208+
}
209+
@keyframes colorMorph {
210+
0% { fill: #${titleColor}; }
211+
25% { fill: #${iconColor}; }
212+
50% { fill: #${textColor}; }
213+
75% { fill: #${iconColor}; }
214+
100% { fill: #${titleColor}; }
195215
}
196216
.bubble {
197217
animation: bubbleFloat 3s infinite ease-in-out;
@@ -208,7 +228,11 @@ const getAnimationStyle = (style, colors, width, height) => {
208228
}
209229
/* Character-by-character wave effect */
210230
.wave-char {
211-
animation: letterWave 2s ease-in-out infinite;
231+
animation: letterWave ${waveSpeed}s ease-in-out infinite;
232+
}
233+
/* Color morphing effect */
234+
.wave-char-morph {
235+
animation: letterWave ${waveSpeed}s ease-in-out infinite, colorMorph ${waveSpeed * 3}s ease-in-out infinite;
212236
}`;
213237

214238
// SVG filter for jellyfish glow
@@ -499,6 +523,10 @@ const renderRepoCard = (repo, options = {}) => {
499523
age_metric = "first",
500524
animation_style = "none",
501525
disable_animations = false,
526+
wave_speed = 2,
527+
wave_amplitude = 3,
528+
wave_delay = 0.05,
529+
color_morph = false,
502530
} = options;
503531

504532
const lineHeight = 10;
@@ -687,8 +715,14 @@ const renderRepoCard = (repo, options = {}) => {
687715

688716
// Get animation styles if enabled
689717
const hasAnimation = !disable_animations && animation_style !== "none";
718+
const waveParams = {
719+
speed: wave_speed,
720+
amplitude: wave_amplitude,
721+
delay: wave_delay,
722+
colorMorph: color_morph,
723+
};
690724
const animationData = hasAnimation
691-
? getAnimationStyle(animation_style, colors, 400, cardHeight)
725+
? getAnimationStyle(animation_style, colors, 400, cardHeight, waveParams)
692726
: { css: "", svg: "" };
693727

694728
// Check if we should add wave effect to text
@@ -736,7 +770,7 @@ const renderRepoCard = (repo, options = {}) => {
736770
${icons.contribs}
737771
</svg>
738772
<text x="25" y="0" class="wave-title" data-testid="header">
739-
${wrapTextInWave(header.length > 35 ? `${header.slice(0, 35)}...` : header)}
773+
${wrapTextInWave(header.length > 35 ? `${header.slice(0, 35)}...` : header, 0, wave_delay, color_morph)}
740774
</text>
741775
</g>
742776
`

0 commit comments

Comments
 (0)