ritual.sh/static/js/button-generator/effects/background-rain.js

117 lines
2.9 KiB
JavaScript

import { ButtonEffect } from '../effect-base.js';
/**
* Raining background effect
* Animated raindrops falling down the button
*/
export class RainBackgroundEffect extends ButtonEffect {
constructor() {
super({
id: 'bg-rain',
name: 'Rain Effect',
type: 'general',
category: 'Background Animations',
renderOrder: 55 // After background, before other effects
});
// Initialize raindrop positions (persistent across frames)
this.raindrops = [];
this.initialized = false;
}
defineControls() {
return [
{
id: 'animate-rain',
type: 'checkbox',
label: 'Rain Effect',
defaultValue: false
},
{
id: 'rain-density',
type: 'range',
label: 'Rain Density',
defaultValue: 15,
min: 5,
max: 30,
step: 1,
showWhen: 'animate-rain',
description: 'Number of raindrops'
},
{
id: 'rain-speed',
type: 'range',
label: 'Rain Speed',
defaultValue: 1.5,
min: 0.5,
max: 3,
step: 0.1,
showWhen: 'animate-rain',
description: 'Speed of falling rain'
},
{
id: 'rain-color',
type: 'color',
label: 'Rain Color',
defaultValue: '#6ba3ff',
showWhen: 'animate-rain',
description: 'Color of raindrops'
}
];
}
isEnabled(controlValues) {
return controlValues['animate-rain'] === true;
}
apply(context, controlValues, animState, renderData) {
if (!animState) return;
const density = controlValues['rain-density'] || 15;
const speed = controlValues['rain-speed'] || 1.5;
const color = controlValues['rain-color'] || '#6ba3ff';
// Initialize raindrops on first frame
if (!this.initialized || this.raindrops.length !== density) {
this.raindrops = [];
for (let i = 0; i < density; i++) {
this.raindrops.push({
x: Math.random() * renderData.width,
y: Math.random() * renderData.height,
length: 2 + Math.random() * 4,
speedMultiplier: 0.8 + Math.random() * 0.4
});
}
this.initialized = true;
}
// Draw raindrops
context.strokeStyle = color;
context.lineWidth = 1;
context.lineCap = 'round';
this.raindrops.forEach(drop => {
// Update position
drop.y += speed * drop.speedMultiplier;
// Reset to top when reaching bottom
if (drop.y > renderData.height + drop.length) {
drop.y = -drop.length;
drop.x = Math.random() * renderData.width;
}
// Draw raindrop
context.globalAlpha = 0.6;
context.beginPath();
context.moveTo(drop.x, drop.y);
context.lineTo(drop.x, drop.y + drop.length);
context.stroke();
context.globalAlpha = 1.0;
});
}
}
// Auto-register effect
export function register(generator) {
generator.registerEffect(new RainBackgroundEffect());
}