Белый шум (зернистость) на черном фоне

Как можно оптимизировано сделать белый шум на черном фоне?

введите сюда описание изображения

Пробовал взять кусок изображения, background-repeat и его анимировать (как шум на старом телевизоре). Получилось то, что нужно, но сайт начинает виснуть. Есть ли более лаконичные и оптимизированные способы, чтобы такое реализовать? Возможно, с помощью js?


Ответы (2 шт):

Автор решения: UserTest013

Сделал пример на js, но думаю лучше обычную гифку сделать и не нагружать браузер.

const canvas = document.getElementById('white-noise');
const ctx = canvas.getContext('2d');

ctx.canvas.height = canvas.offsetHeight;
ctx.canvas.width = canvas.offsetWidth;

render();

function render() {
  const image = ctx.createImageData(ctx.canvas.width, ctx.canvas.height);
  for (let i = 0; i < image.data.length; i += 4) {
    const color = Math.random() * 255;
    image.data[i] = color;
    image.data[i + 1] = color;
    image.data[i + 2] = color;
    image.data[i + 3] = 255;
  }
  ctx.putImageData(image, 0, 0);
  requestAnimationFrame(render);
}
#white-noise {
  width: 100%;
  height: 300px;
}
<canvas id="white-noise"></canvas>

→ Ссылка
Автор решения: Laukhin Andrey

Можно подготовить анимированный gif. Можно подготовить набор фоновых изображений и использовать css-анимацию.

Хорошая рекомендация выше про WebGL, есть уже готовые шейдеры:

Еще видел подобные штуки на SVG-фильтрах.

Но если уж очень хочется ограничиться JS и CSS, и использовать background, то могу предложить такое извращение (берегите глаза):

var canvas = document.createElement("canvas");
var sheet = document.getElementById('tv-css').sheet;
var ctx = canvas.getContext("2d");

let tileSize = 256;

canvas.width = tileSize;
canvas.height = tileSize;

let cssKeyFrames = [];
let frames = 16;
let array = ctx.createImageData(tileSize, tileSize);

for (let i = 0; i < frames; i++) {
  for (let j = 0; j < array.data.length;) {
    const c = ~~(Math.random() * 2) * 255;
    array.data[j++] = c;
    array.data[j++] = c;
    array.data[j++] = c;
    array.data[j++] = 255;
  }
  ctx.putImageData(array, 0, 0);

  let img = canvas.toDataURL("image/jpeg", 0.1);
  cssKeyFrames.push(~~(100 / (frames - 1) * i) +
    '% { background: url(' + img + ') repeat top left/512px 512px; }'
  );
}

let styles = '@keyframes tvShow { ' + cssKeyFrames.join('') + '}';
sheet.insertRule(styles, 1);
<style id="tv-css">
  body {
    animation: tvShow 1s infinite steps(2, end);
  }
</style>

Т.е. генерируем кадры и CSS-правила для анимации. Если сложить все изображения в файлы и самому прописать CSS, то и JS не нужен.

→ Ссылка