Something went wrong. Try again.
2025 refresh of the landing page in Astro
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>OBS Countdown Timer</title> <style> body { margin: 0; padding: 0; overflow: hidden; background-color: transparent; display: flex; justify-content: center; align-items: center; width: 100vw; height: 100vh; font-family: Arial, Helvetica, sans-serif; } #timer { color: white; font-weight: bold; text-shadow: -2px -2px 0 #000, 2px -2px 0 #000, -2px 2px 0 #000, 2px 2px 0 #000, 0px 3px 0 #000, 3px 0px 0 #000, 0px -3px 0 #000, -3px 0px 0 #000; text-align: center; font-size: 10vw; /* Initial size, will be adjusted by JS */ } #error { color: red; background-color: rgba(0, 0, 0, 0.7); padding: 20px; border-radius: 10px; text-align: center; display: none; } </style></head><body> <div id="timer">00:00:00</div> <div id="error">Invalid configuration parameters!</div>
<script> // Function to parse URL fragments function getFragmentParams() { const hash = window.location.hash.substring(1); const params = {}; if (!hash) return params; hash.split('&').forEach(param => { const [key, value] = param.split('='); if (key && value) { params[key] = decodeURIComponent(value); } }); return params; } // Function to format time function formatTime(totalSeconds) { if (totalSeconds < 0) totalSeconds = 0; const hours = Math.floor(totalSeconds / 3600); const minutes = Math.floor((totalSeconds % 3600) / 60); const seconds = Math.floor(totalSeconds % 60); return [ hours.toString().padStart(2, '0'), minutes.toString().padStart(2, '0'), seconds.toString().padStart(2, '0') ].join(':'); } // Function to calculate remaining time function getRemainingTime(startTime, durationSeconds) { const currentTime = new Date().getTime(); const endTime = startTime + (durationSeconds * 1000); return Math.ceil((endTime - currentTime) / 1000); } // Function to get start time from fragments function getStartTime() { const params = getFragmentParams(); // Use provided start time or current time if (params.startYear && params.startMonth && params.startDay) { const year = parseInt(params.startYear, 10); const month = parseInt(params.startMonth, 10) - 1; // JS months are 0-indexed const day = parseInt(params.startDay, 10); const hour = parseInt(params.startHour || '0', 10); const minute = parseInt(params.startMinute || '0', 10); const second = parseInt(params.startSecond || '0', 10); return new Date(year, month, day, hour, minute, second).getTime(); } return new Date().getTime(); } // Function to get duration from fragments function getDuration() { const params = getFragmentParams(); return parseInt(params.lengthSeconds || '3600', 10); // Default 1 hour } // Function to validate configuration function validateConfig() { const params = getFragmentParams(); const startTime = getStartTime(); if (isNaN(startTime) || isNaN(getDuration())) { document.getElementById('error').style.display = 'block'; document.getElementById('timer').style.display = 'none'; return false; } document.getElementById('error').style.display = 'none'; document.getElementById('timer').style.display = 'block'; return true; } // Function to update timer display function updateTimer() { if (!validateConfig()) return; const startTime = getStartTime(); const duration = getDuration(); const remainingSeconds = getRemainingTime(startTime, duration); const timerElement = document.getElementById('timer'); timerElement.textContent = formatTime(remainingSeconds); // If countdown is complete if (remainingSeconds <= 0) { timerElement.textContent = "00:00:00"; // Optionally add a class to change styling when complete timerElement.classList.add('completed'); } else { timerElement.classList.remove('completed'); } // Auto-resize text based on width autoResizeText(); } // Function to auto-resize text to fit container function autoResizeText() { const timerElement = document.getElementById('timer'); const containerWidth = window.innerWidth; const containerHeight = window.innerHeight; // Start with a large font size let fontSize = 20; timerElement.style.fontSize = `${fontSize}vw`; // Calculate the aspect ratio (width to height) const ratio = containerWidth / containerHeight; // Adjust based on aspect ratio if (ratio < 1) { // Portrait mode - use vh timerElement.style.fontSize = `${fontSize}vh`; } else { // Landscape mode - use vw timerElement.style.fontSize = `${fontSize}vw`; } } // Initialize timer updateTimer(); // Update timer every second setInterval(updateTimer, 1000); // Update size on window resize window.addEventListener('resize', autoResizeText); // Listen for hash changes to update configuration window.addEventListener('hashchange', updateTimer); </script></body></html>