← JS

Noise Background

Анимированный шумовой фон на 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