Edited at

ノイズアニメーションをワンタッチで実現する

sample.png

ゾンビランドサガの公式サイト(の一部)でノイズアニメーションが使われているのを見て、「これはライブラリ化できそうだな」と思い立ち、衝動的に作ったのがこちらです。

Noise Maker - デモ

Noise Maker - リポジトリ


ノイズアニメーションのロジック

ゾンビランドサガではこんな画像を別途用意して使っていますが、これを Canvas で動的に生成することで利便性と汎用性を高めることにしました(言い回しが大げさ)。


  1. 仮想 Canvas を作成

  2. 1 ピクセルごとにランダムな RGBA 値を設定

  3. 指定された DOM ノードの背景画像に Data URI として設定

  4. アニメーションループ内で background-position をランダムに設定


NoiseMaker クラスについて

上記のロジックに基づいて作ったのが NoiseMaker クラスです。以下特徴。


  • 複数の DOM ノードに異なるノイズアニメーションを設定可能

  • ノイズアニメーションを削除可能

  • ノイズ画像のサイズを設定可能

  • 各ピクセルの RGBA 値に対して最小乱数値と最大乱数値を設定可能

  • Firefox では若干遅い( background-position の反映が遅い?)

以下コード。

class NoiseMaker {

constructor () {
this.configs = {};
this.configId = 0;
setInterval(() => {
for (let key in this.configs) {
this.configs[key].target.style['background-position'] = `${this.irandom(0, this.configs[key].width)}px ${this.irandom(0, this.configs[key].height)}px`;
}
}, 1);
}
make (config) {
const canvas = document.createElement('canvas');
canvas.setAttribute('width', config.width);
canvas.setAttribute('height', config.height);
const context = canvas.getContext('2d');
const imageData = context.getImageData(0, 0, canvas.width, canvas.height);
for (let y = 0; y < imageData.height; y ++) {
for (let x = 0; x < imageData.width; x ++) {
const index = (imageData.width * y + x) * 4;
imageData.data[index] = this.irandom(config.r[0], config.r[1]);
imageData.data[index + 1] = this.irandom(config.g[0], config.g[1]);
imageData.data[index + 2] = this.irandom(config.b[0], config.b[1]);
imageData.data[index + 3] = this.irandom(config.a[0], config.a[1]);
}
}
context.putImageData(imageData, 0, 0, 0, 0, canvas.width, canvas.height);
config.target.style['background-image'] = `url(${canvas.toDataURL()})`;
this.configs[this.configId.toString()] = config;
return this.configId ++;
}
remove (configId) {
this.configs[configId].target.style['background-image'] = null;
this.configs[configId].target.style['background-position'] = null;
delete this.configs[configId];
}
irandom (min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
}

使い方。

// オブジェクトの作成

const noiseMaker = new NoiseMaker();
// ノイズアニメーションの作成
let configId = noiseMaker.make({
target: document.querySelector('.target'),
width: 320,
height: 320,
r: [ 0, 255 ],
g: [ 0, 255 ],
b: [ 0, 255 ],
a: [ 0, 255 ]
});
// ノイズアニメーションの削除
noiseMaker.remove(configId);

なお、デモでは二箇所に異なるアニメーションを設定しています。


終わりに

即興で書いたので色々アレですが、大体こんな感じで良いと思います。α値を低めに抑えるのがコツですね。あとはアイディア次第で。