console.log( "subSvc.js is loading.." ); if( 1 ) { //preloadの利用 //1. bodyで onload="if( preload ) preload(); else onloadx();" とする。 function preload( event ) { if( ! event ) { //初期設定部分 preload.srcs = []; //2. ここに相対アドレスで指定 for( var name in shapes ) { //check. if( name.indexOf( ">" ) > -1 ) continue; preload.srcs.push( base + name + ".png" ); } preload.srcs.push( base + "りんかく2.png" ); preload.srcs.push( base + "mess1.png" ); preload.srcs.push( base + "mess2.png" ); preload.srcs.push( base + "mess3.png" ); preload.max = preload.srcs.length; preload.cnt = 0; with( preload.element = document.body.appendChild( document.createElement( "div" ) ) ) { id = innerHTML = "preloading.."; style.backgroundColor = "white"; style.position = "fixed"; style.border = "solid 1px black"; style.boxShadow = "0em 0em .5em gray inset"; style.padding = "0.5em"; style.right = 4 + "px"; style.bottom = 4 + "px"; style.backgroundImage = "url(/preloading.png)"; style.backgroundRepeat = "no-repeat"; style.backgroundPosition = "right bottom"; style.backgroundSize = "100% 100%"; } images = new Object(); for( var i = 0; i < preload.srcs.length; i++ ) { var image = new Image(); image.onload = preload; image.src = preload.srcs[ i ]; imageSrcSub = preload.srcs[ i ].replace( base, "" ); images[ imageSrcSub.split( "." )[ 0 ].replace( "/", "_" ) ] = image; //3. "sub/pic1.png" と指定したものは -> images.sub_pic1 でアクセスできる } } else { //onloadごとの部分 preload.cnt ++; var text = "Image " + preload.cnt + " of " + preload.max + " loaded."; preload.element.innerHTML = text; //画面表示 console.log( text ); //コンソール表示 if( preload.cnt == preload.max ) { setTimeout( function() { document.body.removeChild( preload.element ) }, 5000 ); svc_onloadx(); onloadx(); } } }//preload() }//preloadの利用 function svc_onloadx() { if( 1 ) { //canvasの設置 cc = document.createElement( "canvas" ).getContext( "2d" ); if( parentDiv = document.getElementById( "whiteareaID" ) ) { parentDiv.appendChild( cc.canvas ); } else { document.body.appendChild( cc.canvas ); } with( cc.canvas ) { width = 700; height = 700; style.border = "solid 1px black"; style.display = "block"; style.margin = "auto"; } cc.clear = function() { this.clearRect( 0, 0, this.canvas.width, this.canvas.height ); } cc.circle = function( x, y, r, strokeStyle, fillStyle ) { //check. if( ! strokeStyle && ! fillStyle ) { strokeStyle = cc.strokeStyle; } cc.beginPath(); cc.arc( x, y, r, 0, 6.28, false ); cc.closePath(); if( fillStyle ) { cc.fillStyle = fillStyle; cc.fill(); } if( strokeStyle ) { cc.strokeStyle = strokeStyle; cc.stroke(); } } cc.line = function( x1, y1, x2, y2, strokeStyle ) { cc.beginPath(); cc.moveTo( x1, y1 ); cc.lineTo( x2, y2 ); cc.closePath(); if( strokeStyle ) cc.strokeStyle = strokeStyle; cc.stroke(); } } // cc.globalAlpha = 0.5; //---Svc作成 tops = new Array(); svcs = new Object(); zIndex = new Array(); //svc for( var name in shapes ) { //check. if( name.indexOf( ">" ) > -1 ) continue; var shape = shapes[ name ]; var xlCenterX = shape.left + shape.Width / 2; //図形の中心 var xlCenterY = shape.top + shape.Height / 2; //図形の中心 var x = shape.left - shape.diffLeft; var y = shape.top - shape.diffTop; var rad = shape.Rotation * ( Math.PI / 180 ); var k = Svc.utlKaitenC( xlCenterX, xlCenterY, x, y, rad ); var svc = new Svc( { name : name, ax : k.X, //回転後の画像左上座標 ay : k.Y, width : shapes[ name ].saveWidth, height : shapes[ name ].saveHeight, image : images[ name ], imageRxRate : 0.5, imageRyRate : 0, thetaA : rad, zIndex : shapes[ name ].ZOrderPosition, } ); svcs[ name ] = svc; zIndex.push( svc ); } zIndex.sort( function( a, b ) { return ( a.zIndex > b.zIndex ) - ( a.zIndex < b.zIndex ); } ); //connector for( var name in shapes ) { //check. if( name.indexOf( ">" ) == -1 ) continue; var tokens = name.split( ">" ); var parentName = tokens[ 0 ]; var childName = tokens[ 1 ]; var parent = svcs[ parentName ]; var child = svcs[ childName ]; if( parentName == "" ) { //top svc child.isTop = true; tops.push( child ); console.log( "top svc" ); } else if( childName == "" ) { //hand svc console.log( "hand svc" ); } else { //normal svc var parentC = parent.addConnector( name ); var childC = child.addConnector( name ); Svc.connect( parentC, childC ); console.log( "normal svc" ); } } //コネクタの座標 for( var svcName in svcs ) { var svc = svcs[ svcName ]; for( var connectorName in svc.connectors ) { var connector = svc.connectors[ connectorName ]; var connectorShape = shapes[ connectorName ]; var connectorCenterX = connectorShape.left + connectorShape.Width / 2; var connectorCenterY = connectorShape.top + connectorShape.Height / 2; connector.nx = connectorCenterX - svc.ax; connector.ny = connectorCenterY - svc.ay; var k = Svc.utlKaiten( connector.nx, connector.ny, -svc.thetaA ); connector.rx = k.X; connector.ry = k.Y; //回転なしの状態の座標 } } /* //各ax, ayの調整 for( var svcName in svcs ) { var svc = svcs[ svcName ]; console.log( svcName ); svc.ax += svc.connectorC.nx; svc.ay += svc.connectorC.ny; console.log( svc.ax, svc.ay ); } */ // red.connectorC = red.connectors.center; //redの中心(省略可) // red.ax = 200; // red.ay = 100; debug1 = typeof svcs[ "red" ] === "undefined"; if( debug1 ) { svcs[ "りんかく" ].calcByA(); } else { svcs[ "red" ].calcByA(); } draw( cc ); //~frame if( 1 ) { timerMS = 100; poses = { "直立" : { data : [ [ svcs[ "りんかく" ], "thetaR", 6.15, 1000 ], [ svcs[ "首" ], "thetaR", -6.4, 1000 ], [ svcs[ "胸" ], "thetaR", 0, 1000 ], [ svcs[ "腹" ], "thetaR", 6.5, 1000 ], [ svcs[ "腰" ], "thetaR", 0, 1000 ], [ svcs[ "右上腕" ], "thetaR", 1.9, 1000 ], [ svcs[ "右下腕" ], "thetaR", -1.9, 1000 ], [ svcs[ "左上腕" ], "thetaR", 0, 1000 ], [ svcs[ "左下腕" ], "thetaR", 0, 1000 ], [ svcs[ "右手" ], "thetaR", -.2, 1000 ], [ svcs[ "左手" ], "thetaR", 3.14, 1000 ], [ svcs[ "右もも" ], "thetaR", 0, 1000 ], [ svcs[ "右すね" ], "thetaR", .1, 1000 ], [ svcs[ "左もも" ], "thetaR", -.2, 1000 ], [ svcs[ "左すね" ], "thetaR", .35, 1000 ], [ svcs[ "右翼上" ], "thetaR", 5.5, 1000 ], [ svcs[ "右翼下" ], "thetaR", -3, 1000 ], [ svcs[ "右翼先" ], "thetaR", -3.5, 1000 ], [ svcs[ "左翼上" ], "thetaR", -1, 1000 ], [ svcs[ "左翼下" ], "thetaR", 3, 1000 ], [ svcs[ "左翼先" ], "thetaR", -3, 1000 ], [ svcs[ "右かかと" ], "thetaR", -0.05, 1000 ], [ svcs[ "左かかと" ], "thetaR", -0.05, 1000 ], [ svcs[ "右つまさき" ], "thetaR", 0, 1000 ], [ svcs[ "左つまさき" ], "thetaR", 0, 1000 ], ], nextFunc : function() { svcs[ "りんかく" ].image = images[ "りんかく2" ]; if( settingType == 1 ) { anms.addWithPose( poses[ "おっと" ] ); } }, }, "おっと" : { data : [ [ svcs[ "りんかく" ], "thetaR", 6.04, 1000 ], [ svcs[ "首" ], "thetaR", -6.02, 1000 ], [ svcs[ "胸" ], "thetaR", 0.08, 1000 ], [ svcs[ "腹" ], "thetaR", 6, 1000 ], [ svcs[ "腰" ], "thetaR", -0.42, 1000 ], [ svcs[ "右上腕" ], "thetaR", 2.14, 1000 ], [ svcs[ "右下腕" ], "thetaR", -1.42, 1000 ], [ svcs[ "左上腕" ], "thetaR", 0.36, 1000 ], [ svcs[ "左下腕" ], "thetaR", 0.29, 1000 ], [ svcs[ "右手" ], "thetaR", 1.38, 1000 ], [ svcs[ "左手" ], "thetaR", 4.36, 1000 ], [ svcs[ "右もも" ], "thetaR", -0.38, 1000 ], [ svcs[ "右すね" ], "thetaR", 0.079, 1000 ], [ svcs[ "左もも" ], "thetaR", -0.599, 1000 ], [ svcs[ "左すね" ], "thetaR", 0.359, 1000 ], [ svcs[ "右翼上" ], "thetaR", 5.943, 1000 ], [ svcs[ "右翼下" ], "thetaR", -4.04, 1000 ], [ svcs[ "右翼先" ], "thetaR", -1.82, 1000 ], [ svcs[ "左翼上" ], "thetaR", 0.5, 1000 ], [ svcs[ "左翼下" ], "thetaR", 1.82, 1000 ], [ svcs[ "左翼先" ], "thetaR", -1.82, 1000 ], [ svcs[ "右かかと" ], "thetaR", -0.29, 1000 ], [ svcs[ "左かかと" ], "thetaR", -0.279, 1000 ], [ svcs[ "右つまさき" ], "thetaR", -0.06, 1000 ], [ svcs[ "左つまさき" ], "thetaR", -0.1, 1000 ], ], nextFunc : function() { svcs[ "りんかく" ].image = images[ "りんかく" ]; if( settingType == 1 ) { anms.addWithPose( poses[ "直立" ] ); } else { drawMess( cc ); } }, }, }; anms = new Anms( timerMS ); switch( settingType ) { case 1: anms.addWithPose( poses[ "直立" ] ); break; case 2: break; } timerID = setInterval( frame, timerMS ); } else { //frame(); } messIdx = 0; } function Anms( timerMS ) { this.timerMS = timerMS; this.array = new Array(); } Anms.prototype.addWithPose = function( pose ) { pose.endCount = 0; for( var i = 0; i < pose.data.length; i++ ) { var data = pose.data[ i ]; var anm = new Anm( data[ 0 ], data[ 1 ], data[ 2 ], data[ 3 ], this.timerMS ); anm.pose = pose; this.array.push( anm ); } } function Anm( object, member, endValue, tm ) { this.object = object; this.member = member; this.endValue = endValue; this.tm = tm; this.startValue = this.object[ this.member ]; this.length = this.endValue - this.startValue; this.countMax = tm / timerMS; this.stepValue = this.length / this.countMax; this.count = 0; this.endFlg = false; this.direction = this.object[ this.member ] < this.endValue ? 1 : -1; // console.log( this.object.name, this.object[ this.member ], "->", this.endValue ); } Anm.prototype.frame = function() { this.object[ this.member ] += this.stepValue; //check. if( this.direction == 1 && this.object[ this.member ] >= this.endValue || this.direction == -1 && this.object[ this.member ] <= this.endValue ) { this.endFlg = true; this.object[ this.member ] = this.endValue; } } function frame() { var drawFlg = false; for( var i = anms.array.length - 1; i >= 0; i-- ) { var anm = anms.array[ i ]; //check. if( anm.endFlg ) { anms.array.splice( i, 1 ); anm.pose.endCount++; //check. if( anm.pose.endCount == anm.pose.data.length ) { anm.pose.nextFunc() } continue; } anm.frame(); drawFlg = true; } if( 0 ) { if( debug1 ) { svcs[ "右上腕" ].thetaR += .1; svcs[ "りんかく" ].calc(); } else { svcs[ "green" ].thetaR += .1; svcs[ "blue" ].thetaR += .1; svcs[ "red" ].calc(); } } if( drawFlg ) { svcs[ "りんかく" ].calc(); for( var i = 0; i < tops.length; i++ ) { tops[ i ].calc(); } draw( cc ); } } function draw( cc ) { cc.clear(); cc.save(); cc.translate( -245, -195 ); cc.scale( 1.3, 1.3 ); for( var i = 0; i < zIndex.length; i++ ) { var svc = zIndex[ i ]; svc.draw( cc ); } cc.restore(); } function drawMess( cc ) { var w = 180; var h = 150; var name = "mess" + ( messIdx % 3 + 1 ); cc.drawImage( images[ name ], cc.canvas.width - w, 100, w, h ); messIdx ++; } //--- function Svc( args ) { this.name = args.name; this.width = args.width; this.height = args.height; this.image = args.image; this.imageRx = this.width * args.imageRxRate; //画像における原点の位置 this.imageRy = this.height * args.imageRyRate; this.thetaA = args.thetaA; this.isTop = args.isTop; this.ax = args.ax; this.ay = args.ay; this.zIndex = args.zIndex; this.thetaR = 0; this.connectors = new Object(); this.connectorP = null; this.connectorC = new Connector( this, "initial", 0, 0 ); //各所で未定義チェックを省くため } Svc.connect = function( parentConnector, childConnector ) { var parent = parentConnector.owner; var child = childConnector.owner; //check. 現状の接続を解除 if( child.connectorP ) child.connectorP.partner = undefined; if( child.connectorC ) child.connectorC.partner = undefined; child.connectorP = parentConnector; child.connectorC = childConnector; child.connectorP.partner = childConnector; child.connectorC.partner = parentConnector; } Svc.utlKaiten = function( x, y, theta2 ) { var theta1 = Math.atan2( y, x ); var hankei = Math.sqrt( x * x + y * y ); return { X : Math.cos( theta1 + theta2 ) * hankei, Y : Math.sin( theta1 + theta2 ) * hankei }; } Svc.utlKaitenC = function( cx, cy, x, y, theta2 ) { x -= cx; y -= cy; var theta1 = Math.atan2( y, x ); var hankei = Math.sqrt( x * x + y * y ); return { X : Math.cos( theta1 + theta2 ) * hankei + cx, Y : Math.sin( theta1 + theta2 ) * hankei + cy }; } Svc.utlCircle = function( cx, cy, hankei, doFill, doStroke ) { //check. if( ! doFill && ! doStroke ) { doStroke = true; } cc.beginPath(); cc.arc( cx, cy, hankei, 0, 6.28, false ); cc.closePath(); if( doFill ) cc.fill(); if( doStroke ) cc.stroke(); } Svc.prototype.addConnector = function( name, rxRate, ryRate ) { return this.connectors[ name ] = new Connector( this, name, rxRate, ryRate ); } Svc.prototype.calcByA = function() { console.log( "calcByA" ); //相対座標を計算する if( this.connectorP ) { var parent = this.connectorP.owner; this.thetaR = this.thetaA - parent.thetaA; } else { this.thetaR = this.thetaA; } //コネクタを介して連なるSvcについても計算 for( var name in this.connectors ) { var connector = this.connectors[ name ]; //check. 来た道を戻るのを回避 if( connector == this.connectorC ) continue; //check. partner未設定 if( ! connector.partner ) continue; connector.partner.owner.calcByA(); } } Svc.prototype.calc = function() { //~calc //絶対座標を計算する if( this.connectorP ) { var parent = this.connectorP.owner; //connectorP.rx,ryは親の回転により回転。 var x = this.connectorP.rx; var y = this.connectorP.ry; var k = Svc.utlKaiten( x, y, parent.thetaA ); var x = this.connectorC.rx; var y = this.connectorC.ry; var k2 = Svc.utlKaiten( x, y, parent.thetaA + this.thetaR ); this.ax = parent.ax + k.X - k2.X; this.ay = parent.ay + k.Y - k2.Y; this.thetaA = parent.thetaA + this.thetaR; } else { this.thetaA = this.thetaR; } //コネクタを介して連なるSvcについても計算 for( var name in this.connectors ) { var connector = this.connectors[ name ]; //check. 来た道を戻るのを回避 if( connector == this.connectorC ) continue; //check. partner未設定 if( ! connector.partner ) continue; connector.partner.owner.calc(); } } Svc.prototype.draw = function( cc ) { //~draw if( 1 ) { cc.save(); var k = Svc.utlKaiten( this.connectorC.rx, this.connectorC.ry, this.thetaA ); var x = this.ax + k.X; var y = this.ay + k.Y; cc.translate( x, y ); cc.rotate( this.thetaA ); var imageLTX = -this.connectorC.rx; //Left-Top for draw image. var imageLTY = -this.connectorC.ry; cc.drawImage( this.image, imageLTX, imageLTY, this.width, this.height ); //以下デバッグ //図形の中心 if( 0 ) { var shape = shapes[ this.name ]; xlCenterX = imageLTX + shape.diffLeft + shape.Width / 2; //図形の中心 xlCenterY = imageLTY + shape.diffTop + shape.Height / 2; //図形の中心 cc.circle( xlCenterX, xlCenterY, 2, "", "black" ); } //大きな○ コネクタ描画(デバッグとして) if( 0 ) { cc.strokeStyle = "darkred"; for( var name in this.connectors ) { var connector = this.connectors[ name ]; cc.fillStyle = "red"; var x = imageLTX + connector.rx; var y = imageLTY + connector.ry; Svc.utlCircle( x, y, 4, true, true ); cc.fillStyle = "black"; cc.fillText( connector.name, x, y ); } } //水色の小さな□ 回転原点を描画(デバッグとして) if( 0 ) { var sz = 4; var szh = sz / 2; cc.fillStyle = "cyan"; cc.fillRect( - szh, - szh, sz, sz ); cc.strokeStyle = "black"; cc.strokeRect( - szh, - szh, sz, sz ); } //画像枠 if( 0 ) { cc.strokeStyle = "red"; cc.strokeRect( imageLTX, imageLTY, this.width, this.height ); } cc.restore(); } if( 0 ) { cc.strokeStyle = "darkred"; for( var name in this.connectors ) { var connector = this.connectors[ name ]; cc.fillStyle = "red"; x = shapes[ name ].left + shapes[ name ].Width / 2; y = shapes[ name ].top + shapes[ name ].Height / 2; Svc.utlCircle( x, y, 2, true, true ); cc.fillStyle = "black"; cc.fillText( connector.name, x, y ); } cc.save(); var shape = shapes[ this.name ]; xlCenterX = shape.left + shape.Width / 2; //図形の中心 xlCenterY = shape.top + shape.Height / 2; //図形の中心 cc.circle( this.ax, this.ay, 4, "", "blue" ); cc.circle( xlCenterX, xlCenterY, 4, "", "magenta" ); cc.save(); cc.translate( xlCenterX, xlCenterY ); cc.rotate( this.thetaA ); var x = - shape.diffLeft - shape.Width / 2; var y = - shape.diffTop - shape.Height / 2; cc.drawImage( this.image, x, y, this.width, this.height ); cc.strokeStyle = "red"; cc.strokeRect( x, y, this.width, this.height ); cc.restore(); cc.restore(); } } //--- function Connector( owner, name, rxRate, ryRate ) { //コネクタコンストラクタ this.owner = owner; this.name = name; this.rx = owner.width * rxRate; this.ry = owner.height * ryRate; this.nx = 0; this.ny = 0; this.partner = null; }