Dear readers,
Thanks for reading my Blog so frequently in 2025. As a present, I‘ll provide you a HTML file created by Gemini 2.5 Flash.
Please, save and open the following HTML-page. It is safe to do so!
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Happy New Year! - Dynamic Scenery</title>
<style>
body {
margin: 0;
overflow: hidden; /* Hide scrollbars */
background: linear-gradient(to bottom, #0a0a2a 0%, #2c0a4e 100%); /* Dark night sky */
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
position: relative;
color: #fff; /* Default text color */
}
/* Canvas for fireworks */
#fireworksCanvas {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 1; /* Above city, below text */
}
/* "Happy New Year!" Text */
#new-year-text {
position: absolute;
top: 20%; /* Adjust vertical position */
left: 50%;
transform: translate(-50%, -50%);
font-size: 5em; /* Large font size */
font-weight: bold;
text-shadow: 0 0 15px rgba(255, 255, 255, 0.8), 0 0 30px rgba(255, 255, 255, 0.6), 0 0 45px rgba(255, 255, 255, 0.4);
letter-spacing: 5px;
z-index: 2; /* On top of everything */
animation: pulseText 3s infinite alternate; /* Subtle breathing effect */
white-space: nowrap; /* Prevent text wrapping */
}
#new-year-text span {
display: block; /* Ensures text shadow applies properly */
background: linear-gradient(45deg, #ffd700, #ff8c00, #ff4500); /* Gold/Orange gradient */
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text; /* Standard property */
color: transparent; /* Fallback for browsers without -webkit-text-fill-color */
}
@keyframes pulseText {
0% {
transform: translate(-50%, -50%) scale(1);
opacity: 0.9;
}
100% {
transform: translate(-50%, -50%) scale(1.02);
opacity: 1;
}
}
/* City Silhouette at the bottom */
#city-silhouette {
position: absolute;
bottom: 0;
left: 0;
width: 100%;
height: 150px; /* Height of the silhouette */
background: #000; /* Solid black silhouette */
z-index: 0; /* Behind fireworks */
/* Using a simple SVG mask for a jagged city skyline effect */
mask-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><path fill="black" d="M0 100 L0 50 L10 50 L10 70 L20 70 L20 40 L30 40 L30 80 L40 80 L40 60 L50 60 L50 90 L60 90 L60 70 L70 70 L70 50 L80 50 L80 80 L90 80 L90 60 L100 60 L100 100 Z"/></svg>');
mask-size: 100% 100%;
mask-repeat: no-repeat;
-webkit-mask-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><path fill="black" d="M0 100 L0 50 L10 50 L10 70 L20 70 L20 40 L30 40 L30 80 L40 80 L40 60 L50 60 L50 90 L60 90 L60 70 L70 70 L70 50 L80 50 L80 80 L90 80 L90 60 L100 60 L100 100 Z"/></svg>');
-webkit-mask-size: 100% 100%;
-webkit-mask-repeat: no-repeat;
}
/* Twinkling Stars (added via JavaScript) */
.star {
position: absolute;
background-color: white;
border-radius: 50%;
animation: twinkle 2s infinite alternate;
opacity: 0; /* Start invisible */
z-index: 0; /* Behind fireworks */
}
@keyframes twinkle {
0% { opacity: 0; transform: scale(0.5); }
50% { opacity: 1; transform: scale(1); }
100% { opacity: 0; transform: scale(0.5); }
}
</style>
</head>
<body>
<div id="new-year-text">
<span>Happy New Year!</span>
</div>
<canvas id="fireworksCanvas"></canvas>
<div id="city-silhouette"></div>
<script>
const canvas = document.getElementById('fireworksCanvas');
const ctx = canvas.getContext('2d');
let fireworks = [];
let particles = [];
// Set canvas dimensions to full window size
function setCanvasSize() {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
}
setCanvasSize();
window.addEventListener('resize', setCanvasSize);
// Utility function to get a random vibrant color
function getRandomColor() {
const hue = Math.floor(Math.random() * 360);
return `hsl(${hue}, 100%, 70%)`; // High saturation, medium lightness for vibrancy
}
// Particle class for firework trails and explosion fragments
class Particle {
constructor(x, y, vx, vy, color, alphaDecay, size) {
this.x = x;
this.y = y;
this.vx = vx;
this.vy = vy;
this.color = color;
this.alpha = 1;
this.alphaDecay = alphaDecay; // How fast the particle fades
this.size = size;
this.gravity = 0.05; // Affects how particles fall
this.friction = 0.99; // Slows down particles over time
}
update() {
this.vx *= this.friction;
this.vy *= this.friction;
this.vy += this.gravity; // Apply gravity
this.x += this.vx;
this.y += this.vy;
this.alpha -= this.alphaDecay; // Fade out
}
draw() {
ctx.save();
ctx.globalAlpha = Math.max(0, this.alpha); // Ensure alpha doesn't go below 0
ctx.beginPath();
ctx.arc(this.x, this.y, this.size, 0, Math.PI * 2);
ctx.fillStyle = this.color;
ctx.shadowBlur = this.size * 2; // Create a glow effect
ctx.shadowColor = this.color;
ctx.fill();
ctx.restore();
}
}
// Firework class for the rocket and its explosion logic
class Firework {
constructor(startX, startY, targetX, targetY) {
this.x = startX;
this.y = startY;
this.targetX = targetX;
this.targetY = targetY;
// Calculate velocity to reach target
const angle = Math.atan2(targetY - startY, targetX - startX);
this.speed = 5; // Initial rocket speed
this.vx = Math.cos(angle) * this.speed;
this.vy = Math.sin(angle) * this.speed;
this.color = getRandomColor();
this.trail = []; // Particles forming the rocket's trail
this.exploded = false;
}
update() {
if (!this.exploded) {
// Check if firework has reached its target
const distanceToTarget = Math.sqrt((this.x - this.targetX)**2 + (this.y - this.targetY)**2);
if (distanceToTarget <= this.speed) {
this.exploded = true;
this.explode(); // Trigger explosion
} else {
this.x += this.vx;
this.y += this.vy;
// Add particles to the rocket's trail
this.trail.push(new Particle(this.x, this.y, 0, 0, this.color, 0.02, 1.5));
if (this.trail.length > 20) { // Limit trail length for performance
this.trail.shift();
}
}
}
// Update and remove faded trail particles
for (let i = this.trail.length - 1; i >= 0; i--) {
this.trail[i].update();
if (this.trail[i].alpha <= 0.05) {
this.trail.splice(i, 1);
}
}
}
draw() {
if (!this.exploded) {
// Draw the rocket itself
ctx.save();
ctx.beginPath();
ctx.arc(this.x, this.y, 3, 0, Math.PI * 2);
ctx.fillStyle = this.color;
ctx.shadowBlur = 10;
ctx.shadowColor = this.color;
ctx.fill();
ctx.restore();
}
// Draw the rocket's trail
this.trail.forEach(p => p.draw());
}
explode() {
const numParticles = 80 + Math.random() * 50; // Random number of explosion particles
for (let i = 0; i < numParticles; i++) {
const angle = Math.random() * Math.PI * 2; // Random direction
const speed = Math.random() * 8 + 2; // Random speed
const vx = Math.cos(angle) * speed;
const vy = Math.sin(angle) * speed;
const size = Math.random() * 3 + 1; // Random size
particles.push(new Particle(this.x, this.y, vx, vy, this.color, 0.02, size));
}
}
}
// Main animation loop
function animate() {
requestAnimationFrame(animate); // Call animate again on next frame
// Clear canvas with a fading effect to create trails
ctx.globalCompositeOperation = 'destination-out';
ctx.fillStyle = 'rgba(0, 0, 0, 0.1)'; // Fades out previous frames
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.globalCompositeOperation = 'lighter'; // Blend mode for glowing particles
// Update and draw fireworks
for (let i = fireworks.length - 1; i >= 0; i--) {
fireworks[i].update();
fireworks[i].draw();
// Remove firework if it exploded and its trail has faded
if (fireworks[i].exploded && fireworks[i].trail.length === 0) {
fireworks.splice(i, 1);
}
}
// Update and draw explosion particles
for (let i = particles.length - 1; i >= 0; i--) {
particles[i].update();
particles[i].draw();
// Remove particle if it has faded out
if (particles[i].alpha <= 0.05) {
particles.splice(i, 1);
}
}
}
// Function to launch a new firework from the bottom center
function launchFirework() {
const startX = canvas.width / 2;
const startY = canvas.height; // Start from bottom
const targetX = Math.random() * canvas.width * 0.8 + canvas.width * 0.1; // Random target X (within 10%-90% of width)
const targetY = Math.random() * canvas.height * 0.5 + canvas.height * 0.1; // Random target Y (within 10%-60% of height)
fireworks.push(new Firework(startX, startY, targetX, targetY));
}
// Launch fireworks periodically
setInterval(launchFirework, 1000); // Launch a new firework every 1 second
// Initial launch to start the show
launchFirework();
// Start the animation loop
animate();
// Optional: Add twinkling stars to the background using JS
function createStars(numStars) {
const starsContainer = document.body;
for (let i = 0; i < numStars; i++) {
const star = document.createElement('div');
star.classList.add('star');
star.style.width = star.style.height = `${Math.random() * 2 + 1}px`; // Random size 1-3px
star.style.top = `${Math.random() * 100}%`;
star.style.left = `${Math.random() * 100}%`;
star.style.animationDelay = `${Math.random() * 2}s`; // Stagger animation start
star.style.animationDuration = `${Math.random() * 1.5 + 1.5}s`; // Random animation duration
starsContainer.appendChild(star);
}
}
createStars(100); // Create 100 twinkling stars
</script>
</body>
</html>
No comments:
Post a Comment