diff --git a/i-do.mp3 b/i-do.mp3 new file mode 100644 index 0000000..cb42183 Binary files /dev/null and b/i-do.mp3 differ diff --git a/index.html b/index.html new file mode 100644 index 0000000..0890c0e --- /dev/null +++ b/index.html @@ -0,0 +1,70 @@ + + + + + + Valentine Proposal 💝 + + + + +
+ + + +
+ +
+
+ + + + +

+ Làm người yêu mình nhé? 🥰 +

+ +
+ + + +
+ + +
+
+ +
+
+
+ + + +
+
+

+ Cùng bắt đầu hành trình với nhau nhé ❤️ +

+

+ Cảm ơn vì đã chọn mình! +

+
+

+

Chúc mừng chúng ta! 🎉

+
+
+
+ + + + diff --git a/script.js b/script.js new file mode 100644 index 0000000..ced01b2 --- /dev/null +++ b/script.js @@ -0,0 +1,173 @@ +const yesButton = document.getElementById('yesButton'); +const noButton = document.getElementById('noButton'); +const message = document.getElementById('message'); +const mainScreen = document.querySelector('.main-screen'); +const successScreen = document.querySelector('.success-screen'); +const startDate = document.getElementById('startDate'); +const backgroundMusic = document.getElementById('backgroundMusic'); +const successMusic = document.getElementById('successMusic'); +const toggleButton = document.getElementById('toggleMusic'); + +const noButtonTexts = [ + 'Thật sự không? 🥺', + 'Nghĩ lại đi mà 😢', + 'Đừng bấm nữa, đau lòng lắm 💔', + 'Thôi mà, Yes đi 🥹', + 'Làm người yêu tớ đi 😍', + 'Nhớ nghĩ kỹ đấy 🤔', + 'Bấm Yes là đẹp đôi 👀', + 'Vẫn còn cố chấp sao? 😅', + 'Thử nghĩ về tương lai đi 🌟', + 'Ok vậy tớ chọn Yes cho 😘' +]; + +let noCount = 0; +let yesScale = 1; +let isMusicPlaying = true; +let isSuccessScreen = false; + +const handleMusicTransition = async (from, to) => { + if (!isMusicPlaying) return; + + const fadeOutInterval = setInterval(() => { + if (from.volume > 0.1) { + from.volume -= 0.1; + } else { + clearInterval(fadeOutInterval); + from.pause(); + from.volume = 1.0; + playNewMusic(to); + } + }, 100); +}; + +const playNewMusic = async (music) => { + music.volume = 0; + try { + await music.play(); + const fadeInInterval = setInterval(() => { + if (music.volume < 0.9) { + music.volume += 0.1; + } else { + clearInterval(fadeInInterval); + music.volume = 1.0; + } + }, 100); + } catch (error) { + console.log('Music play error:', error); + } +}; + +const initializeAudio = async () => { + try { + backgroundMusic.volume = 0; + await backgroundMusic.play(); + isMusicPlaying = true; + toggleButton.textContent = '🎵 Tạm dừng'; + + const fadeInInterval = setInterval(() => { + if (backgroundMusic.volume < 0.9) { + backgroundMusic.volume += 0.1; + } else { + clearInterval(fadeInInterval); + backgroundMusic.volume = 1.0; + } + }, 100); + } catch (error) { + console.log('Autoplay prevented:', error); + isMusicPlaying = false; + toggleButton.textContent = '🎵 Phát nhạc'; + } +}; + +window.addEventListener('DOMContentLoaded', initializeAudio); + +document.addEventListener('visibilitychange', () => { + if (document.hidden) { + if (isMusicPlaying) { + isSuccessScreen ? successMusic.pause() : backgroundMusic.pause(); + } + } else { + if (isMusicPlaying) { + isSuccessScreen ? successMusic.play() : backgroundMusic.play(); + } + } +}); + +toggleButton.addEventListener('click', () => { + if (isMusicPlaying) { + if (isSuccessScreen) { + successMusic.pause(); + } else { + backgroundMusic.pause(); + } + toggleButton.textContent = '🎵 Phát nhạc'; + } else { + if (isSuccessScreen) { + successMusic.play(); + } else { + backgroundMusic.play(); + } + toggleButton.textContent = '🎵 Tạm dừng'; + } + isMusicPlaying = !isMusicPlaying; +}); + +const animateNoButton = () => { + noButton.classList.add('shake'); + setTimeout(() => noButton.classList.remove('shake'), 500); + + const heart = document.createElement('div'); + heart.innerHTML = '💔'; + heart.style.position = 'absolute'; + heart.style.left = `${Math.random() * 100}%`; + heart.style.top = `${Math.random() * 100}%`; + heart.style.animation = 'float 3s ease-out forwards'; + mainScreen.appendChild(heart); + setTimeout(() => heart.remove(), 3000); +}; + +noButton.addEventListener('click', () => { + noCount++; + yesScale = Math.min(yesScale + 0.15, 2); + yesButton.style.transform = `scale(${yesScale})`; + + if (noCount < noButtonTexts.length) { + noButton.textContent = noButtonTexts[noCount]; + } else { + noButton.disabled = true; + noButton.textContent = 'Hết cách rồi, bấm Yes thôi! 😝'; + noButton.classList.add('opacity-50', 'cursor-not-allowed'); + } + + animateNoButton(); + + message.textContent = noCount < noButtonTexts.length + ? "Bạn vẫn còn cơ hội đổi ý đấy... 😉" + : "Hết cách rồi, giờ chỉ có thể bấm Yes thôi! 😘"; + message.classList.remove('hidden'); +}); + +yesButton.addEventListener('click', () => { + isSuccessScreen = true; + mainScreen.style.display = 'none'; + successScreen.style.display = 'flex'; + startDate.textContent = `Ngày bắt đầu: ${new Date().toLocaleDateString()}`; + + if (isMusicPlaying) { + handleMusicTransition(backgroundMusic, successMusic); + } + + for (let i = 0; i < 10; i++) { + setTimeout(() => { + const heart = document.createElement('div'); + heart.innerHTML = '❤️'; + heart.style.position = 'fixed'; + heart.style.left = `${Math.random() * 100}%`; + heart.style.bottom = '0'; + heart.style.animation = `float ${2 + Math.random() * 3}s ease-out forwards`; + document.body.appendChild(heart); + setTimeout(() => heart.remove(), 5000); + }, i * 300); + } +}); diff --git a/styles.css b/styles.css new file mode 100644 index 0000000..b55908e --- /dev/null +++ b/styles.css @@ -0,0 +1,124 @@ +@keyframes shake { + 0%, 100% { transform: translateX(0); } + 25% { transform: translateX(-5px) rotate(-5deg); } + 75% { transform: translateX(5px) rotate(5deg); } +} + +@keyframes float { + 0%, 100% { transform: translateY(0); } + 50% { transform: translateY(-10px); } +} + +@keyframes fadeIn { + from { opacity: 0; transform: translateY(20px); } + to { opacity: 1; transform: translateY(0); } +} + +@keyframes pulse { + 0%, 100% { opacity: 1; transform: scale(1); } + 50% { opacity: .8; transform: scale(1.1); } +} + +@keyframes floating-hearts { + 0% { transform: translateY(0) translateX(0) rotate(0); opacity: 1; } + 100% { transform: translateY(-100px) translateX(var(--translate-x)) rotate(var(--rotate)); opacity: 0; } +} + +.shake { + animation: shake 0.5s cubic-bezier(.36,.07,.19,.97) both; +} + +.animate-float { + animation: float 2s ease-in-out infinite; +} + +.animate-fade-in { + animation: fadeIn 1s ease-in; +} + +.animate-pulse { + animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite; +} + +.hearts-animation { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + pointer-events: none; +} + +.hearts-animation::before, +.hearts-animation::after { + content: '❤️'; + position: absolute; + font-size: 1.5rem; + animation: floating-hearts 2s ease-in-out infinite; + opacity: 0; +} + +.hearts-animation::before { + --translate-x: -20px; + --rotate: -30deg; + left: 40%; +} + +.hearts-animation::after { + --translate-x: 20px; + --rotate: 30deg; + right: 40%; + animation-delay: 1s; +} + +.music-controls { + position: fixed; + bottom: 20px; + left: 50%; + transform: translateX(-50%); + z-index: 1000; + background: rgba(255, 255, 255, 0.9); + padding: 8px 16px; + border-radius: 9999px; + box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1); + backdrop-filter: blur(5px); +} + +.success-screen { + display: none; +} + +@media (max-width: 640px) { + .music-controls { + bottom: 10px; + padding: 6px 12px; + width: calc(100% - 32px); + max-width: 300px; + } + + .music-controls button { + width: 100%; + } + + .hearts-animation::before, + .hearts-animation::after { + font-size: 1rem; + } +} + +@media (max-height: 500px) and (orientation: landscape) { + .music-controls { + bottom: 5px; + } + + .main-screen, + .success-screen { + padding: 1rem; + } +} + +@media (prefers-color-scheme: dark) { + .music-controls { + background: rgba(0, 0, 0, 0.7); + } +} diff --git a/until-you.mp3 b/until-you.mp3 new file mode 100644 index 0000000..6cd6518 Binary files /dev/null and b/until-you.mp3 differ