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

137 lines
4 KiB
JavaScript

import { ButtonEffect } from '../effect-base.js';
/**
* Rainbow flash background effect
* Animates background through rainbow colors
*/
export class RainbowBackgroundEffect extends ButtonEffect {
constructor() {
super({
id: 'bg-rainbow',
name: 'Rainbow Background',
type: 'background',
category: 'Background Animations',
renderOrder: 2 // After base background
});
}
defineControls() {
return [
{
id: 'animate-bg-rainbow',
type: 'checkbox',
label: 'Rainbow Flash',
defaultValue: false
},
{
id: 'rainbow-speed',
type: 'range',
label: 'Rainbow Speed',
defaultValue: 1,
min: 0.1,
max: 5,
step: 0.1,
showWhen: 'animate-bg-rainbow',
description: 'Speed of rainbow cycling'
}
];
}
isEnabled(controlValues) {
return controlValues['animate-bg-rainbow'] === true;
}
apply(context, controlValues, animState, renderData) {
if (!animState) return;
const speed = controlValues['rainbow-speed'] || 1;
const hue = (animState.progress * speed * 360) % 360;
const bgType = controlValues['bg-type'];
if (bgType === 'solid') {
// Solid rainbow
context.fillStyle = `hsl(${hue}, 70%, 50%)`;
context.fillRect(0, 0, renderData.width, renderData.height);
} else if (bgType === 'gradient') {
// Rainbow gradient
const angle = (controlValues['gradient-angle'] || 90) * (Math.PI / 180);
const x1 = renderData.centerX + Math.cos(angle) * renderData.centerX;
const y1 = renderData.centerY + Math.sin(angle) * renderData.centerY;
const x2 = renderData.centerX - Math.cos(angle) * renderData.centerX;
const y2 = renderData.centerY - Math.sin(angle) * renderData.centerY;
const gradient = context.createLinearGradient(x1, y1, x2, y2);
gradient.addColorStop(0, `hsl(${hue}, 70%, 50%)`);
gradient.addColorStop(1, `hsl(${(hue + 60) % 360}, 70%, 60%)`);
context.fillStyle = gradient;
context.fillRect(0, 0, renderData.width, renderData.height);
}
}
}
/**
* Rainbow gradient sweep effect
* Creates a moving rainbow gradient that sweeps across the button
*/
export class RainbowGradientSweepEffect extends ButtonEffect {
constructor() {
super({
id: 'bg-rainbow-gradient',
name: 'Rainbow Gradient Sweep',
type: 'general',
category: 'Background Animations',
renderOrder: 50 // After background and text
});
}
defineControls() {
return [
{
id: 'animate-bg-rainbow-gradient',
type: 'checkbox',
label: 'Rainbow Sweep',
defaultValue: false,
description: 'Moving rainbow gradient overlay'
}
];
}
isEnabled(controlValues) {
return controlValues['animate-bg-rainbow-gradient'] === true;
}
apply(context, controlValues, animState, renderData) {
if (!animState) return;
// Map progress to position (-100 to 100)
const position = animState.progress * 200 - 100;
// Create a horizontal gradient that sweeps across
const gradient = context.createLinearGradient(
position - 50,
0,
position + 50,
0
);
// Create rainbow stops that also cycle through colors
const hueOffset = animState.progress * 360;
gradient.addColorStop(0, `hsla(${(hueOffset + 0) % 360}, 80%, 50%, 0)`);
gradient.addColorStop(0.2, `hsla(${(hueOffset + 60) % 360}, 80%, 50%, 0.6)`);
gradient.addColorStop(0.4, `hsla(${(hueOffset + 120) % 360}, 80%, 50%, 0.8)`);
gradient.addColorStop(0.6, `hsla(${(hueOffset + 180) % 360}, 80%, 50%, 0.8)`);
gradient.addColorStop(0.8, `hsla(${(hueOffset + 240) % 360}, 80%, 50%, 0.6)`);
gradient.addColorStop(1, `hsla(${(hueOffset + 300) % 360}, 80%, 50%, 0)`);
context.fillStyle = gradient;
context.fillRect(0, 0, renderData.width, renderData.height);
}
}
// Auto-register effects
export function register(generator) {
generator.registerEffect(new RainbowBackgroundEffect());
generator.registerEffect(new RainbowGradientSweepEffect());
}