<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>I See You.</title>
<!-- Importing Inter font for the UI overlay -->
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500&display=swap" rel="stylesheet">
<style>
/* Base page styling */
body, html {
margin: 0;
padding: 0;
width: 100%;
height: 100%;
background-color: #000; /* Dark background to frame the image */
overflow: hidden; /* Hide scrollbars caused by the image zooming out of bounds */
display: flex;
justify-content: center;
align-items: center;
font-family: 'Inter', sans-serif;
}
/* Container that clips the zooming image */
.image-container {
width: 100%;
height: 100%;
overflow: hidden;
position: relative;
}
/*
The image element that will be scaled.
object-fit: cover ensures the image fills the screen optimally
regardless of the screen's aspect ratio.
*/
.zoom-image {
width: 100%;
height: 100%;
object-fit: cover;
/*
Apply the animation:
- name: zoomIn
- duration: 30s
- timing function: linear (constant smooth speed)
- iteration count: infinite (loops forever, resetting abruptly)
*/
animation: zoomIn 30s linear infinite;
transform-origin: center center; /* Zoom towards the center */
}
/* Keyframes defining the start and end of the zoom effect */
@keyframes zoomIn {
0% {
transform: scale(1);
}
100% {
transform: scale(2); /* Adjust this value (e.g., 2.0) for a more intense zoom */
}
}
/* Interactive UI overlay for uploading custom images */
.controls {
position: absolute;
bottom: 30px;
left: 50%;
transform: translateX(-50%);
background: rgba(0, 0, 0, 0.75);
padding: 12px 24px;
border-radius: 12px;
color: white;
display: flex;
gap: 15px;
align-items: center;
/* Keeps the UI unobtrusive until hovered */
opacity: 0.1;
transition: opacity 0.3s ease, transform 0.3s ease;
z-index: 10;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.3);
backdrop-filter: blur(4px);
}
.controls:hover {
opacity: 1;
transform: translateX(-50%) translateY(-5px);
}
.controls label {
font-size: 14px;
font-weight: 500;
}
button, input[type="file"] {
font-family: inherit;
font-size: 14px;
}
button {
background-color: #3b82f6;
color: white;
border: none;
padding: 8px 16px;
border-radius: 6px;
cursor: pointer;
font-weight: 500;
transition: background-color 0.2s;
}
button:hover {
background-color: #2563eb;
}
/* Style the file input to look a bit neater */
input[type="file"]::file-selector-button {
background-color: #4b5563;
color: white;
border: none;
padding: 8px 12px;
border-radius: 6px;
cursor: pointer;
margin-right: 10px;
transition: background-color 0.2s;
}
input[type="file"]::file-selector-button:hover {
background-color: #374151;
}
</style>
</head>
<body>
<div class="image-container">
<!--
Placeholder image.
To hardcode your own 'image.jpg', simply change the src attribute below to "image.jpg".
Alternatively, use the hidden upload controls at the bottom of the screen.
-->
<img id="myImage" class="zoom-image" src=“image.webp” alt=“I See You”>
</div>
<!-- UI Controls (Hover over the bottom center of the screen to reveal) -->
<div class="controls">
<label for="imageUpload">Swap Image:</label>
<input type="file" id="imageUpload" accept="image/*">
<button id="resetAnimation">Restart Zoom</button>
</div>
<script>
document.addEventListener('DOMContentLoaded', () => {
const imageElement = document.getElementById('myImage');
const imageUpload = document.getElementById('imageUpload');
const resetBtn = document.getElementById('resetAnimation');
// Handle dynamic user image upload using the File API
imageUpload.addEventListener('change', function(event) {
const file = event.target.files[0];
if (file) {
// Create a temporary local URL for the uploaded file
const imageUrl = URL.createObjectURL(file);
imageElement.src = imageUrl;
// Restart animation immediately when a new image is loaded
restartAnimation();
}
});
// Handle manual reset of the animation via the button
resetBtn.addEventListener('click', restartAnimation);
// Function to abruptly reset and restart the CSS keyframe animation
function restartAnimation() {
// Temporarily remove the animation class/style
imageElement.style.animation = 'none';
// Force the browser to trigger a reflow (apply the 'none' state instantly)
void imageElement.offsetWidth;
// Re-apply the animation so it starts from 0% again
imageElement.style.animation = 'zoomIn 30s linear infinite';
}
});
</script>
</body>
</html>