Spaces:
Running
Running
Download script.js from Groguru/grogu-s-liquid-bold-lab: direct link, hf CLI and curl.
- Browser
- Download file 7.76 kB
-
https://huggingface.co/spaces/Groguru/grogu-s-liquid-bold-lab/resolve/main/script.js
- Command line
-
hf download hf://spaces/Groguru/grogu-s-liquid-bold-lab/script.js
-
curl -L -o script.js https://huggingface.co/spaces/Groguru/grogu-s-liquid-bold-lab/resolve/main/script.js
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); | |
| }); | |