Новогодний снегопад с поздравлением для любого сайта, скрипт
Украсить ваш сайт снежинками и поздравлениями с новым годом:
Код вставляем перерд закрывающим
Пздравления и снег:
[js_run]
(function() {
‘use strict’;
const CONFIG = {
back: {
count: 35,
minSize: 3,
maxSize: 6,
minSpeed: 0.2,
maxSpeed: 0.7,
swayAmplitude: 1.0,
rotationSpeed: 0.004,
opacityMin: 0.15,
opacityMax: 0.35,
colors: [‘30,100,220’, ‘50,120,230’, ‘70,140,240’]
},
front: {
count: 18,
minSize: 5,
maxSize: 10,
minSpeed: 0.6,
maxSpeed: 1.6,
swayAmplitude: 1.5,
rotationSpeed: 0.012,
opacityMin: 0.6,
opacityMax: 1.0,
colors: [‘20,80,200’, ‘30,100,220’, ‘40,110,235’, ‘60,130,245’]
},
greetingInterval: 60000,
greetingDuration: 6000,
greetings: [
‘🎄 С Новым годом! 🎄’,
‘❄️ Счастья и удачи в новом году! ❄️’,
‘🎁 Пусть всё загаданное сбудется! 🎁’,
‘✨ С Новым годом, дорогие друзья! ✨’,
‘⛄ Мира, тепла и волшебства! ⛄’,
‘🥂 За новый счастливый год! 🥂’
]
};
const canvas = document.createElement(‘canvas’);
canvas.style.cssText = ‘position:fixed;top:0;left:0;width:100%;height:100%;pointer-events:none;z-index:9998;’;
canvas.setAttribute(‘aria-hidden’, ‘true’);
document.body.appendChild(canvas);
const ctx = canvas.getContext(‘2d’, { alpha: true });
let W = window.innerWidth, H = window.innerHeight;
function resize() {
W = window.innerWidth; H = window.innerHeight;
const dpr = Math.min(window.devicePixelRatio || 1, 2);
canvas.width = W * dpr; canvas.height = H * dpr;
ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
}
resize();
let resizeTimer;
window.addEventListener(‘resize’, function(){ clearTimeout(resizeTimer); resizeTimer = setTimeout(resize, 200); });
const SPRITE_PADDING = 4;
const spriteCache = {};
function makeSnowflakeSprite(size, color) {
const key = color + ‘|’ + size.toFixed(1);
if (spriteCache[key]) return spriteCache[key];
const half = Math.ceil(size + SPRITE_PADDING);
const full = half * 2;
const dpr = Math.min(window.devicePixelRatio || 1, 2);
const spr = document.createElement(‘canvas’);
spr.width = full * dpr; spr.height = full * dpr;
const sctx = spr.getContext(‘2d’);
sctx.setTransform(dpr, 0, 0, dpr, 0, 0);
sctx.translate(half, half);
const lineWidth = Math.max(0.6, size * 0.09);
const stroke = ‘rgba(‘ + color + ‘,1)’;
sctx.strokeStyle = stroke; sctx.fillStyle = stroke;
sctx.lineWidth = lineWidth; sctx.lineCap = ’round’;
for (let i = 0; i < 6; i++) {
const angle = (Math.PI / 3) * i;
const dx = Math.cos(angle), dy = Math.sin(angle);
sctx.beginPath(); sctx.moveTo(0, 0); sctx.lineTo(dx * size, dy * size); sctx.stroke();
const branchPositions = [0.4, 0.7];
const branchLength = size * 0.35;
const branchAngle = Math.PI / 5;
for (let b = 0; b < branchPositions.length; b++) {
const pos = branchPositions[b];
const bx = dx * size * pos, by = dy * size * pos;
const bLen = branchLength * (b === 0 ? 1 : 0.7);
sctx.beginPath(); sctx.moveTo(bx, by);
sctx.lineTo(bx + Math.cos(angle - branchAngle) * bLen, by + Math.sin(angle - branchAngle) * bLen);
sctx.stroke();
sctx.beginPath(); sctx.moveTo(bx, by);
sctx.lineTo(bx + Math.cos(angle + branchAngle) * bLen, by + Math.sin(angle + branchAngle) * bLen);
sctx.stroke();
}
}
sctx.beginPath(); sctx.arc(0, 0, lineWidth * 0.9, 0, Math.PI * 2); sctx.fill();
const sprite = { canvas: spr, half: half };
spriteCache[key] = sprite;
return sprite;
}
function snapSize(s) { return Math.round(s * 2) / 2; }
function createFlake(layer, randomY) {
const rawSize = layer.minSize + Math.random() * (layer.maxSize - layer.minSize);
const size = snapSize(rawSize);
const color = layer.colors[(Math.random() * layer.colors.length) | 0];
const sprite = makeSnowflakeSprite(size, color);
return {
x: Math.random() * W,
y: randomY ? Math.random() * H : -20,
size: size, sprite: sprite,
speed: layer.minSpeed + Math.random() * (layer.maxSpeed - layer.minSpeed),
sway: Math.random() * Math.PI * 2,
swaySpeed: 0.01 + Math.random() * 0.02,
rotation: Math.random() * Math.PI * 2,
rotationSpeed: (Math.random() - 0.5) * layer.rotationSpeed * 2,
opacity: layer.opacityMin + Math.random() * (layer.opacityMax - layer.opacityMin),
layer: layer
};
}
function createLayer(cfg) {
const arr = new Array(cfg.count);
for (let i = 0; i < cfg.count; i++) arr[i] = createFlake(cfg, true);
return arr;
}
const backFlakes = createLayer(CONFIG.back);
const frontFlakes = createLayer(CONFIG.front);
function updateFlakes(flakes, dt) {
for (let i = 0; i < flakes.length; i++) {
const f = flakes[i];
f.y += f.speed * dt;
f.sway += f.swaySpeed * dt;
f.rotation += f.rotationSpeed * dt;
const x = f.x + Math.sin(f.sway) * f.layer.swayAmplitude;
const spr = f.sprite;
ctx.globalAlpha = f.opacity < 0.99 ? f.opacity : 1;
ctx.save();
ctx.translate(x, f.y);
if (f.rotation !== 0) ctx.rotate(f.rotation);
ctx.drawImage(spr.canvas, -spr.half, -spr.half, spr.half * 2, spr.half * 2);
ctx.restore();
if (f.y - f.size > H) flakes[i] = createFlake(f.layer, false);
}
ctx.globalAlpha = 1;
}
let lastTime = performance.now();
function animate(now) {
const dt = Math.min((now — lastTime) / 16.67, 3);
lastTime = now;
ctx.clearRect(0, 0, W, H);
updateFlakes(backFlakes, dt);
updateFlakes(frontFlakes, dt);
requestAnimationFrame(animate);
}
requestAnimationFrame(animate);
const greetingEl = document.createElement(‘div’);
greetingEl.style.cssText = [
‘position:fixed’,’top:50%’,’left:50%’,
‘transform:translate(-50%,-50%) scale(0.6)’,
‘background:linear-gradient(135deg,#0a1f4a,#143a80,#1e5bc8)’,
‘color:#fff’,’padding:28px 44px’,’border-radius:20px’,
‘font-family:-apple-system,»Segoe UI»,Roboto,Arial,sans-serif’,
‘font-size:clamp(20px,4vw,42px)’,’font-weight:700′,’text-align:center’,
‘box-shadow:0 0 40px rgba(50,130,255,0.7),0 0 80px rgba(30,100,220,0.4)’,
‘border:1px solid rgba(120,180,255,0.5)’,
‘text-shadow:0 0 12px rgba(120,180,255,0.9)’,
‘pointer-events:none’,’opacity:0′,
‘transition:opacity 0.6s ease,transform 0.6s cubic-bezier(0.18,0.89,0.32,1.28)’,
‘z-index:9999′,’max-width:90vw’,’line-height:1.3′
].join(‘;’);
greetingEl.setAttribute(‘aria-hidden’, ‘true’);
document.body.appendChild(greetingEl);
let lastGreetingIndex = -1;
function showGreeting() {
let idx;
do { idx = (Math.random() * CONFIG.greetings.length) | 0; }
while (idx === lastGreetingIndex && CONFIG.greetings.length > 1);
lastGreetingIndex = idx;
greetingEl.textContent = CONFIG.greetings[idx];
greetingEl.style.opacity = ‘1’;
greetingEl.style.transform = ‘translate(-50%,-50%) scale(1)’;
setTimeout(function() {
greetingEl.style.opacity = ‘0’;
greetingEl.style.transform = ‘translate(-50%,-50%) scale(0.6)’;
}, CONFIG.greetingDuration);
}
setTimeout(showGreeting, 2000);
setInterval(showGreeting, CONFIG.greetingInterval);
})();
[/js_run]
