雪を降らせる。その2
ちょっとずつ改良(?)する
オブジェクトの定義のやりかたがスマートなのか?!
<!DOCTYPE html> <meta charset="utf-8"> <title>Snow</title> <style> body { background-color:black; overflow: hidden; } </style> <body> <script> var Snow = new function () { if ( 'undefined' === typeof addEventListener || 'undefined' === typeof setInterval || 'undefined' === typeof Function.prototype || 'undefined' === typeof Function.prototype.call || 'undefined' === typeof Function.prototype.apply || 'undefined' === typeof Function.prototype.bind || 'undefined' === typeof Object.create ) { return null; } //__ // 整数化 function int (n) { return Math.floor (n); } // 乱数を整数(bからe未満)を返す function randomInt (b, e) { switch (arguments.length) { case 2 : return int (Math.random () * (e - b)) + b; case 1 : return int (Math.random () * b); default : throw new Error; } } // Sin 関数は計算に時間が必要なので前もって計算しておく var sinDeg = new function () { var sintab = [ ]; var sin = Math.sin; var rad = Math.PI / 180; var val = 0; for (var i = 0; i < 360; i++) { sintab[i] = sin (val); val += rad; } // sin 関数本体 return function sinDeg (deg) { return sintab[deg % 360]; }; }; //__ function Timer (interval) { this.interval = interval; } function Starter (cbFunc) { this.timerID = setInterval (cbFunc.bind (this), this.interval); } function Stopper () { clearInterval (this.timerID); this.timerID = null; } //__ Timer.prototype = Object.create ( Timer.prototype, { timerID: { value : null, writable : true, enumerable : false, configurable: false }, interval: { value : null, writable : true, enumerable : true, configurable: false }, start: { value : Starter, writable : false, enumerable : true, configurable: false }, stop: { value : Stopper, writable : false, enumerable : true, configurable: false } }); //__ function Decorator (alpha, size) { this.opacity = alpha / 100 + ''; this.fontSize = size + 'px'; } function Locator (x, y) { this.left = int (x) + 'px'; this.top = int (y) + 'px'; } function Mover (element) { Timer.call (this); this.element = element; } function move (x, y) { return Locator.apply (this.element.style, arguments); } function view () { var C = this.element.ownerDocument.defaultView; return { innerWidth : C.innerWidth, innerHeight: C.innerHeight }; } //__ Mover.prototype = Object.create ( Timer.prototype, { constructor: { value: Mover }, view: { value : view, writable : false, enumerable : false, configurable: false }, move: { value : move, writable : false, enumerable : true, configurable: false } }); //__ function Snow (element) { Mover.apply (this, arguments); this.p = 0; this.x = 0; this.y = 0; this.z = 0; } // Snow の初期化 function snow_init (n) { var v = this.view (); this.x = randomInt (v.innerWidth); this.y = n ? randomInt (v.innerHeight): 0; this.z = randomInt (5, 36); this.p = randomInt (360); this.interval = randomInt (50, 100); Decorator.call (this.element.style, randomInt (30, 100), this.z); } // Snow を作り出す function snow_create (target) { var doc = target.ownerDocument; var e = doc.createElement ('p'); var style = e.style; var obj; e.textContent = '*'; style.color = '#fff'; style.position = 'absolute'; obj = new this (target.appendChild (e)); obj.init (true); obj.start (snow_fall); Snow['#instances'].push (obj); return obj; } // target要素に n個の雪を作る function snow_demo (target, n) { if (0 < n) while (n--) this.create (target); //実験的な例としてクリックしたら落下を止める target.ownerDocument.addEventListener ('click', snow_clickStopper, false); target = null; //メモリーリーク・パターンを断ち切る } // クリックされたことで落下を一時停止にする function snow_clickStopper (event) { var x = Snow['#instances']; var e = event.target; var snow, i; for (i = 0; snow = x[i++]; ) { if (snow.element === e) { snow.timerID ? snow.stop () : snow.start (snow_fall); break; } } } //__ function snow_fall () { var h = this.view ()['innerHeight']; this.y += this.z / this.rakka; this.p += this.yuragi; if (this.y > h) this.init (); this.move ( this.x + sinDeg (this.p) * this.z, this.y ); } //__ Snow['#instances'] = [ ]; Snow.create = snow_create; Snow.demo = snow_demo; //__ Snow.prototype = Object.create ( Mover.prototype, { constructor: { value: Snow }, init: { value : snow_init, writable : false, enumerable : true, configurable: false }, yuragi: { value : 6 }, rakka: { value : 3 } }); //__ return Snow; }; Snow.demo (document.body, 100); </script>