ゾンビランドサガの公式サイト(の一部)でノイズアニメーションが使われているのを見て、「これはライブラリ化できそうだな」と思い立ち、衝動的に作ったのがこちらです。
Noise Maker - デモ
Noise Maker - リポジトリ
ノイズアニメーションのロジック
ゾンビランドサガではこんな画像を別途用意して使っていますが、これを Canvas で動的に生成することで利便性と汎用性を高めることにしました(言い回しが大げさ)。
- 仮想 Canvas を作成
- 1 ピクセルごとにランダムな RGBA 値を設定
- 指定された DOM ノードの背景画像に Data URI として設定
- アニメーションループ内で
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);
なお、デモでは二箇所に異なるアニメーションを設定しています。
終わりに
即興で書いたので色々アレですが、大体こんな感じで良いと思います。α値を低めに抑えるのがコツですね。あとはアイディア次第で。