Анимированный шумовой фон на Canvas — органический живой шум который плавно меняется. Подходит для hero-секций и фонов. Настраиваемые цвета и скорость. Чистый JS без библиотек.
(function(){
const root = document.createElement('div');
document.body.appendChild(root);
const container = root;
try {
const canvas = document.createElement('canvas');
canvas.style.cssText = 'width:100%;height:280px;border-radius:10px;display:block;';
container.appendChild(canvas);
const ctx = canvas.getContext('2d');
function resize() {
canvas.width = canvas.offsetWidth;
canvas.height = canvas.offsetHeight;
}
resize();
window.addEventListener('resize', resize);
// Простой псевдо-шум без библиотек
function noise(x, y, t) {
const n = Math.sin(x * 0.08 + t) * Math.cos(y * 0.06 + t * 0.7)
+ Math.sin((x + y) * 0.05 + t * 1.3)
+ Math.cos(x * 0.03 - y * 0.07 + t * 0.5);
return (n + 3) / 6; // нормализуем 0..1
}
// Цветовые темы
const themes = [
{ name: 'Green', a: [0,255,156], b: [0,80,40] },
{ name: 'Purple', a: [167,139,250],b: [40,20,80] },
{ name: 'Cyan', a: [34,211,238], b: [0,50,70] },
{ name: 'Fire', a: [255,100,0], b: [80,10,0] },
];
let themeIdx = 0;
// UI — кнопки тем
const ui = document.createElement('div');
ui.style.cssText = 'display:flex;gap:8px;margin-bottom:10px;font-family:monospace;flex-wrap:wrap;';
themes.forEach((th, i) => {
const btn = document.createElement('button');
btn.textContent = th.name;
btn.style.cssText = `
padding:6px 14px;
border-radius:20px;
border:1px solid rgba(255,255,255,0.2);
background:${i===0?'rgba(255,255,255,0.15)':'transparent'};
color:rgba(255,255,255,0.7);
font-family:monospace;
font-size:12px;
cursor:pointer;
transition:0.2s;
`;
btn.addEventListener('click', () => {
themeIdx = i;
ui.querySelectorAll('button').forEach((b,j) => {
b.style.background = j===i ? 'rgba(255,255,255,0.15)' : 'transparent';
b.style.color = j===i ? '#fff' : 'rgba(255,255,255,0.7)';
});
});
ui.appendChild(btn);
});
container.insertBefore(ui, canvas);
// Рисуем шум через пиксели
let t = 0;
const SCALE = 4; // размер пикселя — больше = грубее/быстрее
function draw() {
const W = canvas.width;
const H = canvas.height;
if (!W || !H) { requestAnimationFrame(draw); return; }
const cols = Math.ceil(W / SCALE);
const rows = Math.ceil(H / SCALE);
const theme = themes[themeIdx];
for (let row = 0; row < rows; row++) {
for (let col = 0; col < cols; col++) {
const n = noise(col, row, t);
const r = Math.round(theme.b[0] + (theme.a[0] - theme.b[0]) * n);
const g = Math.round(theme.b[1] + (theme.a[1] - theme.b[1]) * n);
const b = Math.round(theme.b[2] + (theme.a[2] - theme.b[2]) * n);
ctx.fillStyle = `rgb(${r},${g},${b})`;
ctx.fillRect(col * SCALE, row * SCALE, SCALE, SCALE);
}
}
// Виньетка
const vignette = ctx.createRadialGradient(W/2, H/2, H*0.2, W/2, H/2, H*0.9);
vignette.addColorStop(0, 'rgba(0,0,0,0)');
vignette.addColorStop(1, 'rgba(0,0,0,0.65)');
ctx.fillStyle = vignette;
ctx.fillRect(0, 0, W, H);
t += 0.018;
requestAnimationFrame(draw);
}
draw();
} catch(e){
console.error(e);
}
})();
👁 6