Groguru's picture
Manual changes saved
04ab97f verified
Raw History Blame Contribute Delete
7.76 kB
// Liquid Bold Lab - Interactive Controls
document.addEventListener('DOMContentLoaded', () => {
const root = document.documentElement;
const text = document.getElementById('grogu-text');
const blocks = document.querySelectorAll('.oil-block');
const panel = document.getElementById('control-panel');
const toggleBtn = document.getElementById('toggle-panel');
const showBtn = document.getElementById('show-panel');
const resetBtn = document.getElementById('reset-all');
// State management
const state = {
speed: 1,
color: 0,
boldness: 50,
spinSpeed: 0.5,
zoom: 1,
oilShine: 80,
softCorners: 20,
depth: 100,
letterSpacing: -0.08,
blockTwist: 15
};
// Slider elements
const sliders = {
speed: document.getElementById('speed'),
color: document.getElementById('color'),
boldness: document.getElementById('boldness'),
spinSpeed: document.getElementById('spin-speed'),
zoom: document.getElementById('zoom'),
oilShine: document.getElementById('oil-shine'),
softCorners: document.getElementById('soft-corners'),
depth: document.getElementById('depth'),
letterSpacing: document.getElementById('letter-spacing'),
blockTwist: document.getElementById('block-twist')
};
// Value displays
const displays = {
speed: document.getElementById('val-speed'),
color: document.getElementById('val-color'),
boldness: document.getElementById('val-bold'),
spinSpeed: document.getElementById('val-spin'),
zoom: document.getElementById('val-zoom'),
oilShine: document.getElementById('val-shine'),
softCorners: document.getElementById('val-blur'),
depth: document.getElementById('val-depth'),
letterSpacing: document.getElementById('val-spacing'),
blockTwist: document.getElementById('val-twist')
};
// Update CSS variables and displays
function updateValue(key, value) {
state[key] = parseFloat(value);
switch(key) {
case 'speed':
root.style.setProperty('--anim-speed', state[key]);
displays[key].textContent = state[key].toFixed(1) + 'x';
break;
case 'color':
root.style.setProperty('--base-hue', state[key]);
displays[key].textContent = Math.round(state[key]) + '°';
// Update thumb color
sliders[key].style.background = `linear-gradient(to right, hsl(${state[key]}, 70%, 50%), hsl(${state[key]}, 70%, 50%))`;
break;
case 'boldness':
root.style.setProperty('--boldness', state[key]);
displays[key].textContent = Math.round(state[key]);
break;
case 'spinSpeed':
root.style.setProperty('--spin-speed', Math.abs(state[key]));
root.style.setProperty('--direction', state[key] >= 0 ? 1 : -1);
displays[key].textContent = state[key].toFixed(1);
break;
case 'zoom':
root.style.setProperty('--zoom', state[key]);
displays[key].textContent = state[key].toFixed(2);
break;
case 'oilShine':
root.style.setProperty('--oil-shine', state[key] / 100);
displays[key].textContent = Math.round(state[key]) + '%';
document.querySelectorAll('.oil-shine').forEach(el => {
el.style.opacity = state[key] / 100;
});
break;
case 'softCorners':
root.style.setProperty('--soft-corners', state[key] + 'px');
displays[key].textContent = Math.round(state[key]) + 'px';
break;
case 'depth':
root.style.setProperty('--depth', state[key] + 'px');
displays[key].textContent = Math.round(state[key]) + 'px';
break;
case 'letterSpacing':
root.style.setProperty('--letter-spacing', state[key] + 'em');
displays[key].textContent = state[key].toFixed(2) + 'em';
break;
case 'blockTwist':
root.style.setProperty('--block-twist', state[key] + 'deg');
displays[key].textContent = Math.round(state[key]) + '°';
break;
}
}
// Event listeners for sliders
Object.keys(sliders).forEach(key => {
if (sliders[key]) {
sliders[key].addEventListener('input', (e) => {
updateValue(key, e.target.value);
});
}
});
// Panel toggle
toggleBtn.addEventListener('click', () => {
panel.classList.add('translate-x-[120%]');
setTimeout(() => {
panel.style.display = 'none';
showBtn.classList.remove('hidden');
}, 300);
});
showBtn.addEventListener('click', () => {
panel.style.display = 'block';
showBtn.classList.add('hidden');
setTimeout(() => {
panel.classList.remove('translate-x-[120%]');
}, 10);
});
// Reset functionality
const defaults = {
speed: 1,
color: 0,
boldness: 50,
spinSpeed: 1,
zoom: 1,
oilShine: 80,
softCorners: 20,
depth: 100,
letterSpacing: -0.08,
blockTwist: 15
};
resetBtn.addEventListener('click', () => {
Object.keys(defaults).forEach(key => {
if (sliders[key]) {
sliders[key].value = defaults[key];
updateValue(key, defaults[key]);
}
});
});
// Mouse interaction for parallax
let mouseX = 0;
let mouseY = 0;
let currentX = 0;
let currentY = 0;
document.addEventListener('mousemove', (e) => {
mouseX = (e.clientX / window.innerWidth - 0.5) * 2;
mouseY = (e.clientY / window.innerHeight - 0.5) * 2;
});
// Smooth animation loop
function animate() {
currentX += (mouseX - currentX) * 0.05;
currentY += (mouseY - currentY) * 0.05;
// Apply subtle parallax to blocks based on mouse
blocks.forEach((block, index) => {
const depth = (index + 1) * 20;
const rotateX = currentY * 10;
const rotateY = currentX * 10;
block.style.transform += ` rotateX(${rotateX}deg) rotateY(${rotateY}deg)`;
});
// Text follows mouse slightly
if (text) {
const moveX = currentX * 30;
const moveY = currentY * 30;
text.style.transform = `translate(${moveX}px, ${moveY}px) scale(var(--zoom))`;
}
requestAnimationFrame(animate);
}
animate();
// Prevent scroll on mobile
document.body.style.overflow = 'hidden';
document.body.style.touchAction = 'none';
// Keyboard shortcuts
document.addEventListener('keydown', (e) => {
if (e.key === 'h') {
toggleBtn.click();
}
if (e.key === ' ') {
e.preventDefault();
// Pause/play animation
const currentSpeed = parseFloat(sliders.speed.value);
if (currentSpeed > 0) {
sliders.speed.value = 0;
updateValue('speed', 0);
} else {
sliders.speed.value = 1;
updateValue('speed', 1);
}
}
});
// Initial reveal
setTimeout(() => {
text.style.opacity = '1';
}, 100);
});