ノイズアニメーションをワンタッチで実現する
ノイズアニメーションをワンタッチで実現する:
ゾンビランドサガの公式サイト(の一部)でノイズアニメーションが使われているのを見て、「これはライブラリ化できそうだな」と思い立ち、衝動的に作ったのがこちらです。
Noise Maker - デモ
Noise Maker - リポジトリ
ゾンビランドサガではこんな画像を別途用意して使っていますが、これを Canvas で動的に生成することで利便性と汎用性を高めることにしました(言い回しが大げさ)。
上記のロジックに基づいて作ったのが NoiseMaker クラスです。以下特徴。
使い方。
なお、デモでは二箇所に異なるアニメーションを設定しています。
即興で書いたので色々アレですが、大体こんな感じで良いと思います。α値を低めに抑えるのがコツですね。あとはアイディア次第で。
ゾンビランドサガの公式サイト(の一部)でノイズアニメーションが使われているのを見て、「これはライブラリ化できそうだな」と思い立ち、衝動的に作ったのがこちらです。
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);
コメント
コメントを投稿