/* このファイルを を使ってHTML内に置くと、 "whiteareaID"というIDを付けたHTML要素の上部にCANVASが表示され、 自動的に動作を開始します。 (最初のH2タグの位置までをCANVASの縦サイズとしています) 以下は、ある程度コメントでプログラムの案内をしています。 */ //オブジェクトに関数を書く様式でプログラムを書いています。 app = { uid : Date.now(), //uidと言ってもデバッグプリントやHTML要素のIDとして使っているだけのものです //ページ読み込み完了時の関数 onload : function( e ) { console.log( this.uid, "onload" ); //CANVAS作成など this.timerID = null; this.timerMS = 120; var canvasElement = document.createElement( "canvas" ); canvasElement.id = "canvas" + this.uid; canvasElement.innerHTML = ''; canvasElement.style.backgroundColor = "RGB(0,32,96)"; this.p = document.getElementById( "whiteareaID" ); this.p.appendChild( canvasElement ); this.cc = document.getElementById( canvasElement.id ).getContext( "2d" ); //ccはCanvasContextの略です //---vars1 //varsの中に星やカメラなどアプリケーションの動きに関する //変数を置いています。「なんかいいことあるかな」と思って。 this.vars = { image : new Image(), pixelStart : 162, cnt : 29, } this.vars.image.onload = function( e ) { } this.vars.image.src = "20191103-indexJS/Sheet1.png"; //画面の上のほうクリックで情報表示 var app = this; this.pixel = this.vars.pixelStart; //2とかにするとファミコンみたいな画質になります。 if( 1 ) { this.cc.canvas.style.imageRendering = "pixelated"; this.cc.canvas.style.imageRendering = "optimizeSpeed"; } this.onresize(); abc = false; setTimeout( function() { abc = true; }, 3000 ); addEventListener( "resize", app.onresize.bind( app ), false ); addEventListener( "scroll", app.onscroll.bind( app ), false ); //このbindというのは、その関数(たとえばonresize)実行時、 //その関数内でthisにあたるオブジェクトを //引数で指定したオブジェクトに変更するというものです。 //これをやらないとthisはwindowになります。 },//onload() //---onresize //ウィンドウリサイズ時の関数 onresize : function( e ) { console.log( this.uid, "onresize" ); var canvasElement = this.cc.canvas; var h2; //homepage6047のページの最初のH2タグ(日記日付を書いているタグ)を検索 for( var i = 0; i < this.p.children.length; i++ ) { var child = this.p.children[ i ]; if( child.tagName == "H2" ) { h2 = child; break; } } //そのH2タグの位置までをCANVASの縦サイズとする var pr = this.p.getBoundingClientRect(); var w = pr.width; var h = h2.offsetTop; with( canvasElement.style ) { position = "absolute"; left = "0px"; top = "0px"; width = w + "px"; height = h + "px"; zIndex = -2; } this.cc.canvasWidth = w; this.cc.canvasHeight = h; //cssのwidthはそのままに、canvasのwidthをpixelで割った小さいサイズに //するので画質が落ちます。 this.cc.canvas.width = w / this.pixel; this.cc.canvas.height = h / this.pixel; this.cc.scale( 1 / this.pixel, 1 / this.pixel ); this.draw( this.cc ); this.onscroll(); //このonscroll関数の中にsetInterval()があり、アニメ開始となる。 },//onresize() //---draw //画面描画 draw : function( cc ) { cc.clearRect( 0, 0, cc.canvasWidth, cc.canvasHeight ); let h = cc.canvasHeight; let rate = h / this.vars.image.height; let w = this.vars.image.width * rate; let offsetW = ( cc.canvasWidth - w ) / 2; cc.drawImage( this.vars.image, offsetW, 0, w, h ); if( this.pixel == 1 ) { cc.font = "24px ''"; cc.fillStyle = "RGBA(255,255,255,0.5)"; let text = "スーパーファミコンみたいなモザイク処理… だけ"; let x = ( cc.canvasWidth - cc.measureText( text ).width ) / 2; let y = cc.canvasHeight - 8; cc.fillText( text, x, y ); } },//draw() //---onscroll //ウィンドウがスクロールされたときの関数 onscroll : function( e ) { //画面外ならスクリプトを停止する。画面内ならスクリプトを開始する。 //そうしないと常にパソコンのCPUを使い続ける(熱を出し続ける)ので… var rect = this.cc.canvas.getBoundingClientRect(); var canvasTop = rect.top; var canvasBottom = rect.top + rect.height; var windowBottom = window.innerHeight; var overTheTop = canvasBottom - 200 < 0; var overTheBottom = canvasTop + 200 > windowBottom; var isVisible = !overTheTop && !overTheBottom; if( this.timerID && !isVisible ) this.stop(); else if( !this.timerID && isVisible ) this.start(); }, //この setInterval() でアニメ開始となる start : function() { console.log( this.uid, "start" ); this.timerID = setInterval( this.frame.bind( this ), this.timerMS ); // this.frame(); }, //アニメ停止 stop : function() { console.log( this.uid, "stop" ); clearInterval( this.timerID ); this.timerID = 0; }, //setInterval()から呼ばれる関数(映像1フレーム分の処理) frame : function() { if( ! abc ) return; this.draw( this.cc ); if( this.pixel == 1 ) return; this.pixel = 0.2 * this.vars.cnt * this.vars.cnt + 0.8; this.vars.cnt --; //check. if( this.pixel < 1 ) { this.pixel = 1; } this.onresize(); },//frame() };//app //ページ読み込み完了で、onload関数を実行する addEventListener( "load", app.onload.bind( app ), false ); //The End of the Script.