|
|
<!DOCTYPE html> |
|
|
<html lang="en"> |
|
|
<head> |
|
|
<meta charset="UTF-8"> |
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0"> |
|
|
<title>Scrolling Love Confession</title> |
|
|
<script src="https://cdn.tailwindcss.com"></script> |
|
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"> |
|
|
<style> |
|
|
@import url('https://fonts.googleapis.com/css2?family=Dancing+Script:wght@700&family=Poppins:wght@300;400;600&display=swap'); |
|
|
|
|
|
body { |
|
|
font-family: 'Poppins', sans-serif; |
|
|
overflow: hidden; |
|
|
background: linear-gradient(-45deg, #ff9a9e, #fad0c4, #fbc2eb, #a6c1ee); |
|
|
background-size: 400% 400%; |
|
|
animation: gradient 15s ease infinite; |
|
|
height: 100vh; |
|
|
} |
|
|
|
|
|
@keyframes gradient { |
|
|
0% { background-position: 0% 50%; } |
|
|
50% { background-position: 100% 50%; } |
|
|
100% { background-position: 0% 50%; } |
|
|
} |
|
|
|
|
|
.heart { |
|
|
position: absolute; |
|
|
pointer-events: none; |
|
|
animation: fall linear forwards; |
|
|
} |
|
|
|
|
|
@keyframes fall { |
|
|
to { |
|
|
transform: translateY(100vh); |
|
|
} |
|
|
} |
|
|
|
|
|
.confession-text { |
|
|
font-family: 'Dancing Script', cursive; |
|
|
text-shadow: 0 2px 4px rgba(0,0,0,0.1); |
|
|
transition: all 0.5s ease; |
|
|
opacity: 0; |
|
|
transform: translateY(20px); |
|
|
} |
|
|
|
|
|
.confession-text.visible { |
|
|
opacity: 1; |
|
|
transform: translateY(0); |
|
|
} |
|
|
|
|
|
.scroll-container { |
|
|
perspective: 1000px; |
|
|
scroll-behavior: smooth; |
|
|
} |
|
|
|
|
|
.scroll-item { |
|
|
transform-style: preserve-3d; |
|
|
transition: transform 0.5s, opacity 0.8s ease-out; |
|
|
} |
|
|
|
|
|
|
|
|
.scroll-container::-webkit-scrollbar { |
|
|
width: 8px; |
|
|
} |
|
|
|
|
|
.scroll-container::-webkit-scrollbar-track { |
|
|
background: rgba(255,255,255,0.2); |
|
|
border-radius: 10px; |
|
|
} |
|
|
|
|
|
.scroll-container::-webkit-scrollbar-thumb { |
|
|
background: rgba(255,105,180,0.6); |
|
|
border-radius: 10px; |
|
|
} |
|
|
|
|
|
.scroll-container::-webkit-scrollbar-thumb:hover { |
|
|
background: rgba(255,105,180,0.8); |
|
|
} |
|
|
|
|
|
|
|
|
.scroll-container { |
|
|
mask-image: linear-gradient( |
|
|
to bottom, |
|
|
transparent 0%, |
|
|
black 10%, |
|
|
black 90%, |
|
|
transparent 100% |
|
|
); |
|
|
} |
|
|
</style> |
|
|
</head> |
|
|
<body class="flex items-center justify-center"> |
|
|
<div class="fixed inset-0 overflow-hidden z-0" id="hearts-container"></div> |
|
|
|
|
|
<div class="relative z-10 w-full max-w-2xl px-4"> |
|
|
<div class="text-center mb-8"> |
|
|
<h1 class="text-4xl md:text-5xl font-bold text-pink-700 mb-2">To My Love</h1> |
|
|
<div class="w-24 h-1 bg-pink-400 mx-auto mb-4"></div> |
|
|
<p class="text-pink-600 italic">Every moment with you feels like a beautiful dream...</p> |
|
|
</div> |
|
|
|
|
|
<div class="scroll-container h-96 overflow-y-auto py-4 px-2 rounded-lg bg-white bg-opacity-20 backdrop-blur-sm shadow-xl"> |
|
|
<div id="confessions" class="space-y-8"> |
|
|
|
|
|
</div> |
|
|
</div> |
|
|
|
|
|
<div class="mt-8 text-center"> |
|
|
<button id="pauseBtn" class="bg-pink-600 hover:bg-pink-700 text-white px-6 py-2 rounded-full shadow-lg transition-all transform hover:scale-105"> |
|
|
<i class="fas fa-pause mr-2"></i>Pause |
|
|
</button> |
|
|
</div> |
|
|
</div> |
|
|
|
|
|
<script> |
|
|
|
|
|
const confessions = [ |
|
|
"From the moment I met you, I knew you were special.", |
|
|
"Your smile brightens even my darkest days.", |
|
|
"I fall in love with you more each day.", |
|
|
"You're the missing piece I've been searching for.", |
|
|
"My heart skips a beat every time I see you.", |
|
|
"You make me believe in love at first sight.", |
|
|
"I cherish every moment we spend together.", |
|
|
"Your laughter is my favorite sound in the world.", |
|
|
"I'm grateful for your love every single day.", |
|
|
"You're my today and all of my tomorrows.", |
|
|
"With you, I've found my happy place.", |
|
|
"You're the reason I believe in soulmates.", |
|
|
"My love for you grows stronger with each passing day.", |
|
|
"You complete me in ways I never knew possible.", |
|
|
"I can't imagine my life without you in it.", |
|
|
"You're my sunshine on cloudy days.", |
|
|
"Every love story is beautiful, but ours is my favorite.", |
|
|
"You're the answer to every prayer I never said.", |
|
|
"I love you more than words can express.", |
|
|
"You're my favorite hello and hardest goodbye." |
|
|
]; |
|
|
|
|
|
|
|
|
function createHearts() { |
|
|
const container = document.getElementById('hearts-container'); |
|
|
const heart = document.createElement('div'); |
|
|
heart.innerHTML = '<i class="fas fa-heart text-pink-500 opacity-70"></i>'; |
|
|
heart.className = 'heart text-2xl'; |
|
|
|
|
|
|
|
|
const xPos = Math.random() * window.innerWidth; |
|
|
heart.style.left = `${xPos}px`; |
|
|
heart.style.top = '-30px'; |
|
|
|
|
|
|
|
|
const size = Math.random() * 20 + 10; |
|
|
heart.style.fontSize = `${size}px`; |
|
|
|
|
|
|
|
|
const duration = Math.random() * 5 + 5; |
|
|
heart.style.animationDuration = `${duration}s`; |
|
|
|
|
|
container.appendChild(heart); |
|
|
|
|
|
|
|
|
setTimeout(() => { |
|
|
heart.remove(); |
|
|
}, duration * 1000); |
|
|
} |
|
|
|
|
|
|
|
|
function addConfessions() { |
|
|
const container = document.getElementById('confessions'); |
|
|
container.innerHTML = ''; |
|
|
|
|
|
confessions.forEach((text, index) => { |
|
|
const div = document.createElement('div'); |
|
|
div.className = 'scroll-item confession-text text-center p-4 rounded-lg'; |
|
|
|
|
|
|
|
|
const colors = ['text-pink-700', 'text-red-600', 'text-purple-700', 'text-rose-600']; |
|
|
const color = colors[index % colors.length]; |
|
|
|
|
|
|
|
|
const sizes = ['text-2xl', 'text-3xl', 'text-xl', 'text-2xl']; |
|
|
const size = sizes[index % sizes.length]; |
|
|
|
|
|
div.className += ` ${color} ${size}`; |
|
|
div.textContent = text; |
|
|
|
|
|
container.appendChild(div); |
|
|
|
|
|
|
|
|
setTimeout(() => { |
|
|
div.classList.add('visible'); |
|
|
}, index * 300); |
|
|
}); |
|
|
} |
|
|
|
|
|
|
|
|
let scrollInterval; |
|
|
let isPaused = false; |
|
|
let scrollSpeed = 30; |
|
|
|
|
|
function startScrolling() { |
|
|
const container = document.querySelector('.scroll-container'); |
|
|
let scrollPos = 0; |
|
|
const scrollHeight = container.scrollHeight - container.clientHeight; |
|
|
let lastTimestamp = 0; |
|
|
|
|
|
function scrollStep(timestamp) { |
|
|
if (!lastTimestamp) lastTimestamp = timestamp; |
|
|
const deltaTime = timestamp - lastTimestamp; |
|
|
lastTimestamp = timestamp; |
|
|
|
|
|
if (!isPaused) { |
|
|
|
|
|
scrollPos += (scrollSpeed * deltaTime) / 1000; |
|
|
|
|
|
if (scrollPos >= scrollHeight) { |
|
|
scrollPos = 0; |
|
|
|
|
|
setTimeout(addConfessions, 500); |
|
|
} |
|
|
|
|
|
container.scrollTo({ |
|
|
top: scrollPos, |
|
|
behavior: 'auto' |
|
|
}); |
|
|
} |
|
|
|
|
|
if (!isPaused) { |
|
|
requestAnimationFrame(scrollStep); |
|
|
} |
|
|
} |
|
|
|
|
|
requestAnimationFrame(scrollStep); |
|
|
} |
|
|
|
|
|
|
|
|
document.addEventListener('DOMContentLoaded', () => { |
|
|
addConfessions(); |
|
|
startScrolling(); |
|
|
|
|
|
|
|
|
setInterval(createHearts, 500); |
|
|
|
|
|
|
|
|
document.getElementById('pauseBtn').addEventListener('click', function() { |
|
|
isPaused = !isPaused; |
|
|
this.innerHTML = isPaused |
|
|
? '<i class="fas fa-play mr-2"></i>Resume' |
|
|
: '<i class="fas fa-pause mr-2"></i>Pause'; |
|
|
|
|
|
this.className = isPaused |
|
|
? 'bg-purple-600 hover:bg-purple-700 text-white px-6 py-2 rounded-full shadow-lg transition-all transform hover:scale-105' |
|
|
: 'bg-pink-600 hover:bg-pink-700 text-white px-6 py-2 rounded-full shadow-lg transition-all transform hover:scale-105'; |
|
|
|
|
|
if (!isPaused) { |
|
|
startScrolling(); |
|
|
} |
|
|
}); |
|
|
}); |
|
|
|
|
|
|
|
|
document.querySelector('.scroll-container').addEventListener('mousemove', (e) => { |
|
|
if (isPaused) return; |
|
|
|
|
|
const items = document.querySelectorAll('.scroll-item'); |
|
|
const centerX = e.currentTarget.offsetWidth / 2; |
|
|
const centerY = e.currentTarget.offsetHeight / 2; |
|
|
const mouseX = e.clientX - e.currentTarget.getBoundingClientRect().left; |
|
|
const mouseY = e.clientY - e.currentTarget.getBoundingClientRect().top; |
|
|
|
|
|
items.forEach((item, index) => { |
|
|
const itemRect = item.getBoundingClientRect(); |
|
|
const itemCenterY = itemRect.top + itemRect.height/2 - e.currentTarget.getBoundingClientRect().top; |
|
|
|
|
|
|
|
|
const distanceX = Math.abs(mouseX - centerX); |
|
|
const distanceY = Math.abs(mouseY - itemCenterY); |
|
|
|
|
|
|
|
|
let rotateX = (mouseY - itemCenterY) / 30; |
|
|
let rotateY = (centerX - mouseX) / 30; |
|
|
let scale = 1 - (distanceX + distanceY) / 3000; |
|
|
|
|
|
|
|
|
rotateX = Math.max(-5, Math.min(5, rotateX)); |
|
|
rotateY = Math.max(-5, Math.min(5, rotateY)); |
|
|
scale = Math.max(0.98, Math.min(1.02, scale)); |
|
|
|
|
|
item.style.transform = `rotateX(${rotateX}deg) rotateY(${rotateY}deg) scale(${scale})`; |
|
|
item.style.opacity = 1 - (distanceY / 500); |
|
|
}); |
|
|
}); |
|
|
|
|
|
|
|
|
document.querySelector('.scroll-container').addEventListener('mouseleave', () => { |
|
|
const items = document.querySelectorAll('.scroll-item'); |
|
|
items.forEach(item => { |
|
|
item.style.transform = 'rotateX(0) rotateY(0) scale(1)'; |
|
|
item.style.opacity = 1; |
|
|
}); |
|
|
}); |
|
|
</script> |
|
|
<p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=NJU-Jet/mylove" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body> |
|
|
</html> |