function App( canvas ) { this.cc = canvas.getContext( "2d" ); this.sc = 1; this.L = 0; this.T = 0; //論理座標(プログラム上の座標)を変えずに、画面の粗さだけを変える let onresize = function( e ) { console.log( "onresize" ); let canvas = this.cc.canvas; this.canvasRect = canvas.getBoundingClientRect(); //枠サイズ分 let cs = getComputedStyle( canvas ); let array = [ cs.borderLeftWidth.replace( /px/, "" ) - 0, cs.borderRightWidth.replace( /px/, "" ) - 0, cs.borderTopWidth.replace( /px/, "" ) - 0, cs.borderBottomWidth.replace( /px/, "" ) - 0, ]; this.canvasRect.width -= array[ 0 ] + array[ 1 ]; this.canvasRect.height -= array[ 2 ] + array[ 3 ]; this.screenWidth = canvas.parentNode.getBoundingClientRect().width; this.screenHeight = 512; canvas.width = this.screenWidth; canvas.height = this.screenHeight; //pixel canvas.width /= this.pixelWidth; canvas.height /= this.pixelHeight; canvas.style.width = this.screenWidth + "px"; canvas.style.height = this.screenHeight + "px"; this.draw( this.cc ); }.bind( this ); models = new Array(); cube = new Object(); cube.tens = [ [ -1, +1, -1 ], //0 [ +1, +1, -1 ], //1 [ +1, -1, -1 ], //2 [ -1, -1, -1 ], //3 [ -1, +1, +1 ], //4 [ +1, +1, +1 ], //5 [ +1, -1, +1 ], //6 [ -1, -1, +1 ], //7 ]; cube.mens = [ [ -1, 0, 1, 2, 3 ], //正面 ]; cube.size = 100; cube.pos = [ 0, 0, 1000 ]; cube.rotation = [ 0, 0, 0 ]; models.push( cube ); //イラスト model = { tens : new Array(), mens : new Array(), size : 1, pos : [0, 0, 1000], rotation: [ 11.1, 22.2, 0 ], }; models.push( model ); illust = model; illustDir = -20; /* mensの要素、menのフォーマット ベジェ曲線を含む場合 [ -2, Object, [ idx1 ], //要素数1の配列。moveTo用 [ idx1, idx2, idx3 ], //bezierCurveTo用 [ idx1, idx2, idx3 ], //bezierCurveTo用 [ idx1, idx2, idx3 ], //bezierCurveTo用 ... ] */ //drawSourceを解析 text = this.drawSource.toString(); text = text.match( /\{([\s\S]*)\}/ )[ 1 ]; text = text.replace( /^\s*\n\s*/g, "" ); text = text.replace( /\n\s*/g, "\n" ); text = text.replace( /\n$/, "" ); lines = text.split( /\n/ ); for( let i = 0; i < lines.length; i++ ) { if( tokens = lines[ i ].match( /cc\.(.+?)\((.*)\)/ ) ) { //cc.func( arg1, arg2 ); の場合 tokens.shift(); console.log( tokens.length, tokens.join( " | " ) ); inst = tokens[ 0 ]; args = tokens[ 1 ]; switch( inst ) { case "beginPath": men = new Array(); men.push( -2 ); //-2は、ベジェであるという意味 men.push( properties = new Object() ); model.mens.push( men ); break; case "moveTo": a = args.split( /,/ ).map( str => Number( eval( str ) ) ); idx = model.tens.length; model.tens[ idx ] = [ a[ 0 ], a[ 1 ], 0 ]; men.push( [ idx ] ); break; case "bezierCurveTo": a = args.split( /,/ ).map( str => Number( eval( str ) ) ); idx = model.tens.length; model.tens[ idx ] = [ a[ 0 ], a[ 1 ], 0 ]; model.tens[ idx + 1 ] = [ a[ 2 ], a[ 3 ], 0 ]; model.tens[ idx + 2 ] = [ a[ 4 ], a[ 5 ], 0 ]; men.push( [ idx, idx + 1, idx + 2 ] ); break; case "stroke": properties[ "stroke" ] = true; break; case "fill": properties[ "fill" ] = true; break; } } else if( tokens = lines[ i ].match( /cc\.(.+?)\s*=\s*(.+?);/ ) ) { //cc.variable = value; の場合 tokens.shift(); console.log( tokens.length, tokens.join( " | " ) ); let name = tokens[ 0 ]; let value = tokens[ 1 ].replace( /^"|"$/g, "" ); properties[ name ] = value; } }//for console.log( "models.length", models.length ); cam = new Object(); cam.s = 50; cam.zoom = 14.25; //---mode switch switch( 2 ) { case 1: //イラスト作成用 this.pixelWidth = 1; this.pixelHeight = 1; document.getElementById( "ctrls" ).style.display = "block"; //---cookie read console.log( "read", document.cookie ); pairs = document.cookie.split( /;/ ); for( let i = 0; i < pairs.length; i++ ) { pair = pairs[ i ].split( /=/ ); name = pair[ 0 ].replace( /\s/g, "" ); value = Number( pair[ 1 ] ); console.log( name, value ); switch( name ) { case "sc": case "L": case "T": this[ name ] = value; break; } } onresize( null ); image = new Image(); image.onload = function() { this.draw( this.cc, true ); }.bind( this ); image.src = "/cgi-bin/prj/20190831-素材/3Dお姉さん/normal2.png"; onmousemove = function( e ) { let ax = 0; let ay = 0; let x = scrollX + e.x - 9; let y = scrollY + e.y - 9; x /= this.sc; y /= this.sc; x -= this.cc.canvas.width / 2 + this.L; y -= this.cc.canvas.height / 2 + this.T; x = Math.floor( x ); y = -Math.floor( y ); str = x + ", " + y; this.cc.fillStyle = "white"; this.cc.fillRect( ax, ay, 100, 12 ); this.cc.fillStyle = "black"; this.cc.fillText( str, ax, ay+10 ); }.bind( this ); console.log( this.cc.canvas.width, this.cc.canvas.height ); str= ""; canvas.onclick = function( e ) { if( event.shiftKey ) { console.log( str ); } else { location.reload(); } } //---key onkeyup = function( e ) { ss = 16; // console.log( e.which ); if( e.ctrlKey ) { switch( e.which ) { case 37: this.L += ss; break; //tenkey case 39: this.L -= ss; break; //tenkey case 38: this.T += ss; break; //tenkey case 40: this.T -= ss; break; //tenkey default: return; } } else { switch( e.which ) { case 33: this.sc ++; break; //rollup case 34: this.sc --; break; //rolldown case 29: break; default: return; } } //---cookie write document.cookie = "sc=; max-age=0;"; document.cookie = "L=; max-age=0;"; document.cookie = "T=; max-age=0;"; document.cookie = "sc=" + this.sc + ";"; document.cookie = "L=" + this.L + ";"; document.cookie = "T=" + this.T + ";"; this.draw( this.cc, true ); }.bind( this ); break; case 2: //実行用 with( this.cc.canvas ) { style.imageRendering = "crisp-edges"; style.zIndex = -1; style.position = "absolute"; style.left = 0; style.top = 0; } this.pixelWidth = 1; this.pixelHeight = 1; onresize( null ); this.timerMs = 100; //ページスクロールでストップするしくみ //どの要素を対象にしますか this.target = this.cc.canvas; //要素が何%見えたらアクティブにしますか this.targetPer = 0.5; this.isActive = false; addEventListener( "scroll", this.onscrollx.bind( this ) ); this.onscrollx(); break; } window.addEventListener( "resize", onresize, false ); }//App App.prototype.start = function() { this.timerID = setInterval( this.frame.bind( this ), this.timerMs ); } App.prototype.stop = function() { clearInterval( this.timerID ); } App.prototype.onscrollx = function( e ) { var rect = this.target.getBoundingClientRect(); var targetTopP = ( rect.top ) + ( rect.height * this.targetPer ); var targetBottomP = ( rect.top + rect.height ) - ( rect.height * this.targetPer ); var windowTop = 0; var windowBottom = window.innerHeight; var overTheTop = targetBottomP < windowTop; //ウィンドウ上方へ隠れた var overTheBottom = targetTopP > windowBottom; //ウィンドウ下方へ隠れた var isVisible = ! overTheTop && ! overTheBottom; if( ! this.isActive && isVisible ) { this.isActive = true; this.start(); } else if( this.isActive && ! isVisible ) { this.isActive = false; this.stop(); } } /* メソッド drawSource() の記述ルール closePath()は使用せず、代わりに bezierCurveTo( 前行同メソッド3番目の座標, この図の最初のmoveToの座標, 同座標 ) を用いること。 */ cols = { normal : { hada: "rgb(254,254,154)", mouth: "rgb(255,113,183)", kami: "rgb(73,68,42)", bkami: "rgb(58,54,33)", tensi: "white", mabu: "black", kurome: "black", kirame: "white", kousai: "rgb(29,27,16)", hou: "rgb(251,212,181)", mayu: "rgb(52,48,28)", stick: "white", point: "red", stickL: "rgb(9,172,237)", }, pink : { hada: "rgb(254,254,154)", mouth: "rgb(255,113,183)", kami: "rgb(255,113,183)", bkami: "deeppink", tensi: "white", mabu: "black", kurome: "black", kirame: "white", kousai: "rgb(155,13,83)", hou: "rgb(251,212,181)", mayu: "rgb(52,48,28)", stick: "white", point: "red", stickL: "rgb(9,172,237)", }, green : { hada: "rgb(254,254,154)", mouth: "rgb(255,113,183)", kami: "#00fa9a", bkami: "mediumseagreen", tensi: "white", mabu: "black", kurome: "black", kirame: "white", kousai: "dodgerblue", hou: "rgb(251,212,181)", mayu: "rgb(52,48,28)", stick: "white", point: "red", stickL: "rgb(9,172,237)", }, red : { hada: "rgb(254,254,154)", mouth: "rgb(255,113,183)", kami: "crimson", bkami: "brown", tensi: "white", mabu: "black", kurome: "black", kirame: "white", kousai: "firebrick", hou: "rgb(251,212,181)", mayu: "rgb(52,48,28)", stick: "white", point: "red", stickL: "rgb(9,172,237)", }, }; col = cols.normal; App.prototype.drawSource = function( cc ) { //後ろ髪 cc.beginPath(); cc.moveTo( -133, -152 ); cc.bezierCurveTo( -105, -124, 105, -124, 133, -152 ); cc.bezierCurveTo( 133, -152, 148, -46, 148, -46 ); cc.bezierCurveTo( 148, -46, -148, -46, -148, -46 ); cc.bezierCurveTo( -148, -46, -133, -152, -133, -152 ); cc.fillStyle = col.bkami; cc.fill(); cc.strokeStyle = "red"; cc.stroke(); //りんかく //りんかく cc.beginPath(); cc.moveTo( -129, -81 ); cc.bezierCurveTo( -99,-156, -50, -169 , 0, -171 ); cc.bezierCurveTo( 58,-170, 110, -120, 116, -90 ); cc.bezierCurveTo( 116, -90, 139, 28, 139, 28 ); cc.bezierCurveTo( 139, 28, 27, 137, 27, 137 ); cc.bezierCurveTo( 27, 137, -131, 93, -131, 93 ); cc.bezierCurveTo( -131, 93, -129, -81, -129, -81 ); cc.fillStyle = col.hada; cc.fill(); //耳 cc.beginPath(); cc.moveTo( 119, -57 ); cc.bezierCurveTo( 121, -67, 123, -80, 140, -74 ); cc.bezierCurveTo( 140, -74, 121, -29, 121, -29 ); cc.fillStyle = col.hada; cc.fill(); //くち cc.beginPath(); cc.moveTo( -45, -76 ); cc.bezierCurveTo( -60,-103,-35,-145,0, -145 ); cc.bezierCurveTo( 35,-145,60,-110,47, -76 ); cc.bezierCurveTo( 45, -76,-45, -76,-45, -76 ); cc.fillStyle = col.mouth; cc.fill(); //左目 茶 cc.beginPath(); cc.moveTo( 49,8 ); cc.bezierCurveTo( 15,8, 15, -44, 49,-44 ); cc.bezierCurveTo( 84,-44, 84, 8, 49,8 ); cc.fillStyle = col.kousai; cc.fill(); //左目 黒 cc.beginPath(); cc.moveTo( 49,-9 ); cc.bezierCurveTo( 38,-9, 38, -25, 49,-25 ); cc.bezierCurveTo( 60,-25, 60, -9, 49,-9 ); cc.fillStyle = col.kurome; cc.fill(); //左目 白 cc.beginPath(); cc.moveTo( 38,6 ); cc.bezierCurveTo( 28,6, 28, -11, 38,-11 ); cc.bezierCurveTo( 51,-11, 51, 6, 38,6 ); cc.fillStyle = col.kirame; cc.fill(); //右目 茶 cc.beginPath(); cc.moveTo( 49-101,8 ); cc.bezierCurveTo( 15-101,8, 15-101, -44, 49-101,-44 ); cc.bezierCurveTo( 84-101,-44, 84-101, 8, 49-101,8 ); cc.fillStyle = col.kousai; cc.fill(); //右目 黒 cc.beginPath(); cc.moveTo( 49-101,-9 ); cc.bezierCurveTo( 38-101,-9, 38-101, -25, 49-101,-25 ); cc.bezierCurveTo( 60-101,-25, 60-101, -9, 49-101,-9 ); cc.fillStyle = col.kurome; cc.fill(); //右目 白 cc.beginPath(); cc.moveTo( 38-101,6 ); cc.bezierCurveTo( 28-101,6, 28-101, -11, 38-101,-11 ); cc.bezierCurveTo( 51-101,-11, 51-101, 6, 38-101,6 ); cc.fillStyle = col.kirame; cc.fill(); //左目 まぶた cc.beginPath(); cc.moveTo( 24,5); cc.bezierCurveTo( 55+15,42+12, 128,-17+3, 95,-51 ); cc.bezierCurveTo( 118,-7, 69,42, 24,5 ); cc.fillStyle = col.mabu; cc.fill(); //右目 まぶた cc.beginPath(); cc.moveTo( -2-24,5); cc.bezierCurveTo( -2-55+15-30,42+12, -2-128,-17+3, -2-95,-51 ); cc.bezierCurveTo( -2-118,-7, -2-69,42, -2-24,5 ); cc.fillStyle = col.mabu; cc.fill(); //前髪 cc.beginPath(); cc.moveTo( -120, 18 ); cc.bezierCurveTo( -120, 18, -66, 18, -66, 18 ); cc.bezierCurveTo( -67, 48, -55, 86, -40, 107 ); cc.bezierCurveTo( -51, 85, -55, 30, -46, 16 ); cc.bezierCurveTo( -39, 13, 18, 13, 28, 17 ); cc.bezierCurveTo( 37, 40, 29, 91, 18, 111 ); cc.bezierCurveTo( 30, 97, 51, 40, 48, 18 ); cc.bezierCurveTo( 48, 18, 70, 18, 70, 18 ); cc.bezierCurveTo( 72, 40, 56, 84, 45, 100 ); cc.bezierCurveTo( 52, 95, 85, 42, 85, 18 ); cc.bezierCurveTo( 85, 18, 111, 18, 111, 18 ); cc.bezierCurveTo( 111, 18, 111, 109, 111, 109 ); cc.bezierCurveTo( 111, 109, 1, 145, 1, 145 ); cc.bezierCurveTo( -105, 112, -120, 100, -120, 100 ); cc.bezierCurveTo( -120, 112, -120, 18, -120, 18 ); cc.fillStyle = col.kami; cc.fill(); //上髪 cc.beginPath(); cc.moveTo( 0, 159 ); cc.bezierCurveTo( -100, 160, -175, 85, -158, -2 ); cc.bezierCurveTo( -158, -2, -135, -2, -135, -2 ); cc.bezierCurveTo( -135, -2, -98, 96, -98, 96 ); cc.bezierCurveTo( -98, 96, 0, 136, 0, 136 ); cc.bezierCurveTo( 0, 136, 98, 96, 98, 96 ); cc.bezierCurveTo( 98, 96, 110, 39, 110, 39 ); cc.bezierCurveTo( 110, 39, 135, -2, 135, -2 ); cc.bezierCurveTo( 135, -2, 152, -2, 152, -2 ); cc.bezierCurveTo( 170, 75, 100, 160, 0, 159 ); cc.fillStyle = col.kami; cc.fill(); //左髪 cc.beginPath(); cc.moveTo( 107, 43 ); cc.bezierCurveTo( 120, 15, 118, -155, 110, -173 ); cc.bezierCurveTo( 131, -160, 123, -73, 123, -42 ); cc.bezierCurveTo( 128, -65, 131, -150, 127, -160 ); cc.bezierCurveTo( 143, -149, 164, -125, 167, -103 ); cc.bezierCurveTo( 169, -84, 161, -42, 157, -20 ); cc.bezierCurveTo( 162, -37, 180, -110, 167, -123 ); cc.bezierCurveTo( 195, -90, 155, -20, 154, 32 ); cc.bezierCurveTo( 154, 32, 107, 43, 107, 43 ); cc.fillStyle = col.kami; cc.fill(); //右髪 cc.beginPath(); cc.moveTo( -112, 43 ); cc.bezierCurveTo( -128, 5, -136, -143, -122, -166 ); cc.bezierCurveTo( -138, -157, -165, -132, -166, -113 ); cc.bezierCurveTo( -172, -69, -160, -5, -160, 23 ); cc.bezierCurveTo( -160, 23, -112, 43, -112, 43 ); cc.fillStyle = col.kami; cc.fill(); //左 まゆげ cc.beginPath(); cc.moveTo( 22, 48 ); cc.bezierCurveTo( 31, 56, 81-3, 59-3, 96, 45 ); cc.bezierCurveTo( 81, 52, 40,55, 22,48 ); cc.fillStyle = col.mayu; cc.fill(); //右 まゆげ cc.beginPath(); cc.moveTo( -22-11, 48 ); cc.bezierCurveTo( -31-11, 56, -78-11, 59-3, -96-11, 45 ); cc.bezierCurveTo( -81-11, 52, -40-11,55, -22-11,48 ); cc.fill(); //左ほう cc.beginPath(); cc.moveTo( 82, -76 ); cc.bezierCurveTo( 86, -66, 93, -62, 104, -64 ); cc.bezierCurveTo( 99, -65, 94, -68, 93, -74 ); cc.bezierCurveTo( 96, -71, 105, -70, 109, -74 ); cc.bezierCurveTo( 103, -75, 98, -82, 96, -86 ); cc.bezierCurveTo( 96, -83, 97, -79, 100, -77 ); cc.bezierCurveTo( 94, -77, 87, -81, 86, -85 ); cc.bezierCurveTo( 85, -79, 87, -72, 92, -69 ); cc.bezierCurveTo( 89, -69, 83, -73, 82, -76 ); cc.fillStyle = col.hou; cc.fill(); //右ほう cc.beginPath(); cc.moveTo( 82-198, -74 ); cc.bezierCurveTo( 86-198, -66, -108, -57, 104-198, -64+5 ); cc.bezierCurveTo( -99, -60, 94-198, -66, -104, -71 ); cc.bezierCurveTo( -100, -67, -90, -66, -84, -69 ); cc.bezierCurveTo( -93, -72, -96, -78, -96, -84 ); cc.bezierCurveTo( -98, -81, -98, -75, -96, -73 ); cc.bezierCurveTo( -102, -73, -108, -79, -109, -83 ); cc.bezierCurveTo( -111, -77, -110, -70, -107, -66 ); cc.bezierCurveTo( -110, -67, -114, -71, 82-198, -74 ); cc.fill(); //天使の輪 //右端 cc.beginPath(); cc.moveTo( -4, 117 ); cc.bezierCurveTo( -4, 117, 3, 117, 4, 117 ); cc.bezierCurveTo( 6, 110, 9, 80, 7, 72 ); cc.bezierCurveTo( 7, 72, -6, 72, -6, 72 ); cc.bezierCurveTo( -7, 76, -6, 107, -4, 117 ); cc.fillStyle = col.tensi; cc.fill(); //そのとなり cc.beginPath(); cc.moveTo( -29, 118 ); cc.bezierCurveTo( -29, 118, -27, 118, -27, 118 ); cc.bezierCurveTo( -27, 118, -27, 116, -27, 116 ); cc.bezierCurveTo( -27, 116, -25, 118, -25, 118 ); cc.bezierCurveTo( -25, 118, -12, 117, -9, 118 ); cc.bezierCurveTo( -9, 118, -12, 72, -12, 72 ); cc.bezierCurveTo( -17, 72, -35, 73, -42, 75 ); cc.bezierCurveTo( -43, 82, -33, 116, -29, 118 ); cc.fill(); //左 cc.beginPath(); cc.moveTo( -73, 81 ); cc.bezierCurveTo( -69, 92, -47, 126, -46, 126 ); cc.bezierCurveTo( -49, 124, -51, 122, -55, 117 ); cc.bezierCurveTo( -55, 117, -53, 122, -53, 122 ); cc.bezierCurveTo( -61, 121, -79, 128, -82, 132 ); cc.bezierCurveTo( -82, 132, -85, 131, -85, 131 ); cc.bezierCurveTo( -85, 131, -83, 133, -83, 133 ); cc.bezierCurveTo( -83, 133, -84, 135, -84, 135 ); cc.bezierCurveTo( -93, 132, -113, 116, -116, 111 ); cc.bezierCurveTo( -116, 111, -115, 109, -115, 109 ); cc.bezierCurveTo( -112, 112, -110, 114, -106, 117 ); cc.bezierCurveTo( -106, 117, -115, 108, -114, 107 ); cc.bezierCurveTo( -110, 98, -92, 85, -78, 83 ); cc.bezierCurveTo( -73, 93, -66, 105, -63, 109 ); cc.bezierCurveTo( -63, 109, -76, 86, -76, 82 ); cc.bezierCurveTo( -76, 82, -73, 81, -73, 81 ); cc.fill(); //ポインタ //棒1 cc.beginPath(); cc.moveTo( -256, 81 ); cc.bezierCurveTo( -256, 81, -264, 159, -264, 159 ); cc.bezierCurveTo( -264, 159, -257, 159, -257, 159 ); cc.bezierCurveTo( -257, 159, -249, 82, -249, 82 ); cc.strokeStyle = col.stickL; cc.fillStyle = col.stick; cc.lineWidth = 4; cc.stroke(); cc.fill(); //棒2 cc.beginPath(); cc.moveTo( -249, -2 ); cc.bezierCurveTo( -249, -2, -258, 81, -258, 81 ); cc.bezierCurveTo( -258, 81, -247, 82, -247, 82 ); cc.bezierCurveTo( -247, 82, -238, 0, -238, 0 ); cc.stroke(); cc.fill(); //棒3 cc.beginPath(); cc.moveTo( -252, -2 ); cc.bezierCurveTo( -252, -2, -236, -1, -236, -1 ); cc.bezierCurveTo( -236, -1, -220, -158, -220, -159 ); cc.bezierCurveTo( -220, -159, -234, -161, -234, -161 ); cc.bezierCurveTo( -234, -161, -252, -2, -252, -2 ); cc.stroke(); cc.fill(); //下部 cc.beginPath(); cc.moveTo( -234, -166 ); cc.bezierCurveTo( -234, -166, -219, -165, -219, -165 ); cc.bezierCurveTo( -219, -165, -218, -175, -218, -175 ); cc.bezierCurveTo( -218, -175, -233, -177, -233, -177 ); cc.bezierCurveTo( -233, -177, -234, -166, -234, -166 ); cc.stroke(); cc.fill(); //上部赤丸 cc.beginPath(); cc.moveTo( -261, 177 ); cc.bezierCurveTo( -248, 178, -248, 157, -261, 157 ); cc.bezierCurveTo( -275, 157, -275, 177, -261, 177 ); cc.strokeStyle = col.stickL; cc.fillStyle = col.point; cc.stroke(); cc.fill(); //右手 cc.beginPath(); cc.moveTo( -224, -66 ); cc.bezierCurveTo( -174, -67, -174, -141, -224, -144 ); cc.bezierCurveTo( -275, -142, -275, -67, -224, -66 ); cc.fillStyle = col.hada; cc.fill(); //テキストエリア実行 with( this ) { eval( ta1.value ); } //---ラスト } b=-198; d=2; App.prototype.frame = function() { // if( models[ 1 ].pos[2] == 1000 ) { // alert( models[ 1 ].rotation.join( ", " ) ); // } //自転 for( let i = 0; i < models.length; i++ ) { models[ i ].rotation[ 1 ] += 0.1; //Y if( i == 1 ) models[ i ].rotation[ 0 ] += 0.05; //X } //前後移動 illust.pos[ 2 ] += illustDir; //check. let minZ = 300; let maxZ = 2500; if( illustDir < 0 && illust.pos[ 2 ] < minZ ) { //もっとも近寄った illustDir *= -1; illust.pos[ 2 ] = minZ; //ついで do { nxt = cols[ Object.keys( cols )[ Math.floor( Math.random() * Object.keys( cols ).length ) ] ]; } while( nxt == col ); col = nxt; } else if( illustDir > 0 && illust.pos[ 2 ] > maxZ ) { //もっとも遠ざかった illustDir *= -1; illust.pos[ 2 ] = maxZ; //ついで do { nxt = cols[ Object.keys( cols )[ Math.floor( Math.random() * Object.keys( cols ).length ) ] ]; } while( nxt == col ); col = nxt; } this.draw( this.cc ); // this.timerId = setTimeout( this.run.bind( this ), this.timerMs ); } App.prototype.draw = function( cc, isDrawSource ) { cc.clearRect( 0, 0, this.screenWidth, this.screenHeight ); if( isDrawSource ) { cc.save(); cc.scale( this.sc, this.sc ); // cc.translate( left, top ); if( 1 ) { //元画像 cc.save(); H=500; // H=0; cc.translate( this.screenWidth / 2 - 48+this.L+H, this.screenHeight / 2+this.T ); // cc.globalAlpha = .75; let w = image.width / 2; let h = image.height / 2; cc.drawImage( image, - w / 2, - h / 2, w, h ); cc.restore(); } if( 0 ) { //マス目 cc.save(); cc.translate( this.screenWidth / 2+this.L, this.screenHeight / 2+this.T ); let kankaku = 20; let xmax = 15; let ymax = 10; cc.strokeStyle = "rgba(0,0,255,.5)"; //縦線 for( let x = -xmax; x <= xmax; x++ ) { let top = ymax * kankaku; cc.beginPath(); cc.moveTo( x * kankaku, -top ); cc.lineTo( x * kankaku, top ); cc.closePath(); cc.stroke(); if( x % 2 ) cc.fillText( x * kankaku, x * kankaku - kankaku / 2 , top + 10 ); } //横線 for( let y = -ymax; y <= ymax; y++ ) { let left = xmax * kankaku; cc.beginPath(); cc.moveTo( -left, y * kankaku ); cc.lineTo( left, y * kankaku ); cc.closePath(); cc.stroke(); if( y % 2 ) cc.fillText( y * kankaku, left, y * kankaku ); } cc.restore(); } if( 1 ) { //座標軸 cc.lineWidth = 2; //横線 cc.beginPath(); cc.moveTo( 0, this.screenHeight / 2 + this.T ); cc.lineTo( this.screenWidth, this.screenHeight / 2 + this.T ); cc.closePath(); cc.stroke(); //縦線 cc.beginPath(); cc.moveTo( this.screenWidth / 2 + this.L, 0 ); cc.lineTo( this.screenWidth / 2 + this.L, this.screenHeight ); cc.closePath(); cc.stroke(); cc.lineWidth = 1; } cc.save(); cc.scale( 1 / this.pixelWidth, - 1 / this.pixelHeight ); cc.translate( this.screenWidth / 2+this.L, - this.screenHeight / 2-this.T ); this.drawSource( cc ); cc.restore(); cc.restore(); return; }//if cc.save(); cc.scale( 1 / this.pixelWidth, - 1 / this.pixelHeight ); cc.translate( this.screenWidth / 2, - this.screenHeight / 2 ); for( let l = 0; l < models.length; l++ ) { let model = models[ l ]; //点を計算 let tensC = new Array(); for( let i = 0; i < model.tens.length; i++ ) { let ten = model.tens[ i ]; let x = ten[ 0 ]; let y = ten[ 1 ]; let z = ten[ 2 ]; x *= model.size; y *= model.size; z *= model.size; //自転 let a; //X軸回転 a = this.mathRotate( z, y, model.rotation[ 0 ] ); z = a.x; y = a.y; //Y軸回転 a = this.mathRotate( x, z, model.rotation[ 1 ] ); x = a.x; z = a.y; x += model.pos[ 0 ]; y += model.pos[ 1 ]; z += model.pos[ 2 ]; let h = x * ( cam.s / z ) * cam.zoom; let v = y * ( cam.s / z ) * cam.zoom; tensC[ i ] = { x : x, y : y, z : z, h : h, v : v, } }//for i //面 for( let i = 0; i < model.mens.length; i++ ) { let men = model.mens[ i ]; if( men[ 0 ] == -1 ) { //通常描画 cc.beginPath(); for( let j = 1; j < men.length; j++ ) { let tenIdx = men[ j ]; let ten = tensC[ tenIdx ]; cc[ j == 1 ? "moveTo" : "lineTo" ]( ten.h, ten.v ); } cc.closePath(); cc.stroke(); } else { //ベジェ描画 let properties = men[ 1 ]; cc.beginPath(); for( let j = 2; j < men.length; j++ ) { if( j == 2 ) { let tenIdx = men[ j ][ 0 ]; let ten = tensC[ tenIdx ]; cc.moveTo( ten.h, ten.v ); } else { let sIdx = men[ j ][ 0 ]; let eIdx = men[ j ][ 1 ]; let pIdx = men[ j ][ 2 ]; let s = tensC[ sIdx ]; let e = tensC[ eIdx ]; let p = tensC[ pIdx ]; cc.bezierCurveTo( s.h, s.v, e.h, e.v, p.h, p.v ); } } if( properties.fill ) { if( properties.fillStyle ) { cc.fillStyle = eval( properties.fillStyle ); } cc.fill(); } if( properties.stroke ) { if( properties.strokeStyle ) { cc.strokeStyle = eval( properties.strokeStyle ); } cc.stroke(); } } } }//for l cc.restore(); }//draw() App.prototype.mathRotate = function( x, y, theta2 ) { let hankei = Math.sqrt( x * x + y * y ); let theta1 = Math.atan2( y, x ); return { x : Math.cos( theta1 + theta2 ) * hankei, y : Math.sin( theta1 + theta2 ) * hankei, }; } addEventListener( "load", function() { //check. if( typeof apps === "undefined" ) apps = new Array(); app = new App( document.getElementById( "app2020_04_canvas" ) ); apps.push( app ); }, false );