forked from vyla-entertainment/home-frontend
149 lines
5.4 KiB
JavaScript
149 lines
5.4 KiB
JavaScript
import { qs, isMobileViewport } from '../utils/dom.js';
|
|
import { copyToClipboard, flashFeedback, flashClass } from '../utils/clipboard.js';
|
|
import { typewriterReveal } from '../animations/typewriter.js';
|
|
import { initFluidByteField } from '../animations/fluid-byte-field.js';
|
|
import { DISCORD_LOADER_SCRIPT, COPY_FEEDBACK_DURATION_MS } from '../config/constants.js';
|
|
|
|
const HERO_GREETING = 'Vyla Home';
|
|
|
|
function initVideoColorExtraction() {
|
|
const videos = document.querySelectorAll('.hero-atmosphere-video');
|
|
if (videos.length === 0) return;
|
|
|
|
console.log('Video color extraction initialized, found', videos.length, 'videos');
|
|
|
|
const canvas = document.createElement('canvas');
|
|
const ctx = canvas.getContext('2d', { willReadFrequently: true });
|
|
let animationFrameId;
|
|
let frameCount = 0;
|
|
let currentVideoColor = 'rgb(0, 0, 0)';
|
|
|
|
function extractColors() {
|
|
const video = videos[0];
|
|
if (video.readyState < 2) {
|
|
console.log('Video not ready, readyState:', video.readyState);
|
|
animationFrameId = requestAnimationFrame(extractColors);
|
|
return;
|
|
}
|
|
|
|
try {
|
|
canvas.width = 64;
|
|
canvas.height = 64;
|
|
ctx.drawImage(video, 0, 0, 64, 64);
|
|
const imageData = ctx.getImageData(0, 0, 64, 64);
|
|
const data = imageData.data;
|
|
|
|
let r = 0, g = 0, b = 0;
|
|
let count = 0;
|
|
|
|
for (let i = 0; i < data.length; i += 4) {
|
|
r += data[i];
|
|
g += data[i + 1];
|
|
b += data[i + 2];
|
|
count++;
|
|
}
|
|
|
|
r = Math.round(r / count);
|
|
g = Math.round(g / count);
|
|
b = Math.round(b / count);
|
|
|
|
currentVideoColor = `rgb(${r}, ${g}, ${b})`;
|
|
const dominantColorTransparent = `rgba(${r}, ${g}, ${b}, 0.5)`;
|
|
|
|
document.documentElement.style.setProperty('--video-dominant-color', currentVideoColor);
|
|
document.documentElement.style.setProperty('--video-dominant-color-transparent', dominantColorTransparent);
|
|
|
|
if (window.scrollY === 0) {
|
|
document.documentElement.style.setProperty('--color-bg', currentVideoColor);
|
|
}
|
|
|
|
frameCount++;
|
|
if (frameCount % 30 === 0) {
|
|
console.log('Frame', frameCount, '- Extracted color:', currentVideoColor);
|
|
console.log('CSS variable set:', getComputedStyle(document.documentElement).getPropertyValue('--video-dominant-color'));
|
|
}
|
|
} catch (e) {
|
|
console.error('Error extracting video colors:', e);
|
|
}
|
|
|
|
animationFrameId = requestAnimationFrame(extractColors);
|
|
}
|
|
|
|
function handleScroll() {
|
|
const scrollY = window.scrollY;
|
|
const heroHeight = window.innerHeight;
|
|
const scrollProgress = Math.min(scrollY / (heroHeight * 0.5), 1);
|
|
|
|
const videoColorRGB = currentVideoColor.match(/\d+/g);
|
|
if (videoColorRGB) {
|
|
const r = Math.round(parseInt(videoColorRGB[0]) * (1 - scrollProgress));
|
|
const g = Math.round(parseInt(videoColorRGB[1]) * (1 - scrollProgress));
|
|
const b = Math.round(parseInt(videoColorRGB[2]) * (1 - scrollProgress));
|
|
const fadedColor = `rgb(${r}, ${g}, ${b})`;
|
|
document.documentElement.style.setProperty('--color-bg', fadedColor);
|
|
}
|
|
}
|
|
|
|
animationFrameId = requestAnimationFrame(extractColors);
|
|
window.addEventListener('scroll', handleScroll, { passive: true });
|
|
handleScroll();
|
|
|
|
videos.forEach(video => {
|
|
video.addEventListener('pause', () => {
|
|
console.log('Video paused, stopping color extraction');
|
|
cancelAnimationFrame(animationFrameId);
|
|
});
|
|
|
|
video.addEventListener('play', () => {
|
|
console.log('Video playing, starting color extraction');
|
|
animationFrameId = requestAnimationFrame(extractColors);
|
|
});
|
|
});
|
|
}
|
|
|
|
function initHeroTitle() {
|
|
const heroTitle = qs('.hero-title');
|
|
if (heroTitle) typewriterReveal(heroTitle, HERO_GREETING);
|
|
}
|
|
|
|
function initDiscordCopyBar() {
|
|
const copyBtn = document.getElementById('copy-discord-btn');
|
|
const copyLabel = document.getElementById('copy-discord-label');
|
|
const copyIcon = document.getElementById('copy-discord-icon');
|
|
if (!copyBtn) return;
|
|
|
|
copyBtn.addEventListener('click', async () => {
|
|
await copyToClipboard(DISCORD_LOADER_SCRIPT);
|
|
if (copyIcon) flashClass(copyIcon, 'copied', COPY_FEEDBACK_DURATION_MS);
|
|
});
|
|
}
|
|
|
|
function initHeroCopyButton() {
|
|
const heroCopyScriptBtn = document.getElementById('hero-copy-script-btn');
|
|
if (!heroCopyScriptBtn) return;
|
|
|
|
heroCopyScriptBtn.addEventListener('click', async () => {
|
|
await copyToClipboard(DISCORD_LOADER_SCRIPT);
|
|
flashFeedback(heroCopyScriptBtn, 'Copied!', COPY_FEEDBACK_DURATION_MS);
|
|
});
|
|
}
|
|
|
|
function initCtaCopyButton() {
|
|
const ctaCopyScriptBtn = document.getElementById('cta-copy-script-btn');
|
|
if (!ctaCopyScriptBtn) return;
|
|
|
|
ctaCopyScriptBtn.addEventListener('click', async () => {
|
|
await copyToClipboard(DISCORD_LOADER_SCRIPT);
|
|
flashFeedback(ctaCopyScriptBtn, 'Copied!', COPY_FEEDBACK_DURATION_MS);
|
|
});
|
|
}
|
|
|
|
export function initHeroSection() {
|
|
initHeroTitle();
|
|
initDiscordCopyBar();
|
|
initHeroCopyButton();
|
|
initCtaCopyButton();
|
|
initVideoColorExtraction();
|
|
initFluidByteField('hero-byte-overlay');
|
|
initFluidByteField('cta-byte-overlay');
|
|
} |