function App( target, drawers, sampleview, limitMs ) { //target は canvas を配置するHTML要素 this.target = target; //drawers の各要素は関数である。drawer関数と名付ける。 //drawer関数は、Canvasのパス機能を使って1つの絵を描く通常の関数である。 //drawer関数を Canvasコンテキストを引数に指定して呼び出すと普通に描画を行う。 //Appはdrawers[ 0 ]関数が描く絵 から drawers[ 1 ]関数が描く絵へのモーフィングを行う。 //これらdrawer関数のスクリプトを変換してデータを作成している関係上、 //これらdrawer関数の記述には一定の規則が要求されているので注意。 //規則の説明は現在行っていない。 this.drawers = drawers; this.sampleview = sampleview; //setTimeoutで指定するミリ秒(アニメの滑らかさに影響する) this.timerMs = 100; //変更してよい。1~200程度、100が標準。 this.cc = document.createElement( "canvas" ).getContext( "2d" ); /* //代入文対応: //cc.strokeStyle など代入文で設定を行うものを関数で書けるようにする。 this.cc.setStrokeStyle = function( r, g, b, a ) { this.strokeStyle = "rgba(" + r + "," + g + "," + b + "," + a + ")"; } this.cc.setFillStyle = function( r, g, b, a ) { this.fillStyle = "rgba(" + r + "," + g + "," + b + "," + a + ")"; } this.cc.setLineWidth = function( w ) { this.lineWidth = w; } */ //canvasの見た目の設定(変更してよい) with( this.cc.canvas ) { width = 512; height = 448; style.border = "solid 0px black"; } this.target.appendChild( this.cc.canvas ); //drawer関数のスクリプトを読み、データにする。 /* データの形式 app.データ名.parts = { パーツ名1 : [ [ パス描画関数名1, その引数1, その引数2, ... ], [ パス描画関数名2, その引数1, その引数2, ... ], ... ], パーツ名2 : [ [ パス描画関数名1, その引数1, その引数2, ... ], [ パス描画関数名2, その引数1, その引数2, ... ], ... ], ... } drawer関数の例 App.prototype.draw_usi = function( cc ) { //---path //migi tuno cc.save(); cc.translate( 0, 0 ); cc.lineWidth = 1; cc.strokeStyle = "rgba(0,0,0,1)"; cc.fillStyle = "rgba(245,230,210,1)"; cc.beginPath(); cc.moveTo( -57, -81 ); cc.bezierCurveTo( -65, -87, -85, -88, -90, -88 ); ... //---/path } それをデータにした例 parts = { "migi tuno" : [ [ "save" ], [ "translate", 0, 0 ], [ "setLineWidth", 1 ], [ "setStrokeStyle", 0,0,0,1 ], [ "setFillStyle", 245,230,210,1 ], [ "beginPath" ], [ "moveTo", -57, -81 ], [ "bezierCurveTo", -65, -87, -85, -88, -90, -88 ], ... } */ //アニメの完了時間(変更して良い。ミリ秒 1000ミリ秒=1秒) this.limitMs = limitMs; //---最初のアニメ実行の分の設定 this.fromData = null; this.toData = null; this.toggle = true; //クリックされるたびに、2つのデータを行き来するという演出を行うため //2つのデータを fromData, toData に入れる。 //toggleで判別する。 this.anms = null; this.initData();//fromData, toData, anms を初期化する //canvasがクリックされたら2つのデータを行き来するようにアニメする。 this.cc.canvas.onclick = function( e ) { this.initData(); }.bind( this ); //---スライダで動かす分の設定 this.range1 = document.createElement( "input" ); this.range1.type = "range"; this.range1.id = "range1"; this.target.appendChild( this.range1 ); with( this.range1.style ) { height = "8px" border = "solid 8px #99c"; webkitAppearance = "none"; appearance = "none"; backgroundColor = "yellow"; height = "5px"; width = "100%"; borderRadius = "4px"; } let rangeWidth = this.cc.canvas.width; this.range1.style.width = rangeWidth + "px"; this.range1.max = this.limitMs / this.timerMs; //アニメの完了時間 ÷ setTimeoutで指定するミリ秒 = アニメコマ全数 this.range1.step = 1; //スライダが動かされたらスライダの位置に対応するコマを描画する。 this.range1.oninput = function( e ) { this.frameGoto( e.target.value ); }.bind( this ); //あとはstart()を実行すれば最初のアニメが実行され、 //スライダを動かせば任意のアニメコマの描画を行う。 }//App App.prototype.initData = function() { //クリックされるたびにこの initData() は呼ばれるが、 //2つのデータを行き来させるため、データを入れ替える。 this.fromData = this.funcToData( this.drawers[ this.toggle ? 0 : 1 ] ); this.toData = this.funcToData( this.drawers[ this.toggle ? 1 : 0 ] ); //check. 2つのデータに問題がないかチェックする let result; result = this.check( this.fromData, this.toData ); if( result != true ) alert( result ); //逆にしてチェック result = this.check( this.toData, this.fromData ); if( result != true ) alert( result ); //makeAnms_beziermorph()は2つのデータをモーフィングするアニメデータを返す。 this.anms = this.makeAnms_beziermorph( this.fromData, this.toData, this.limitMs ); this.toggle = ! this.toggle; } App.prototype.funcToData = function( drawer ) { let data = new Object(); //drawer関数を読み、 let functext = drawer.toString().match( /\/\/---path[\s\S]*\/\/---\/path/ )[ 0 ]; //データにする(文字列加工) let s = functext; //以下は複雑。 //作成するデータの形式を、関数と代入文とで処理分けしたくないので //Canvas命令のうち、cc.strokeStyle など代入文で設定を行うものを関数で書き直す。 s = s.replace( /cc\.(.)(.+?) = (.+?);/g, function( m, a, b, c ) { let valuename = a + b; let funcname = 'set' + a.toUpperCase() + b; let rgbaMatchRes = c.match( /"rgba\(\s*(\d+,\d+,\d+,[\d\.]+)\s*\)"/i ); //drawer関数に記述された代入文を関数に置き換えしたいので、 //canvasコンテキストへ関数を定義 if( rgbaMatchRes ) { //rgba形式を代入する代入文の関数 this.cc[ funcname ] = function( r, g, b, a ) { this[ valuename ] = "rgba(" + r + "," + g + "," + b + "," + a + ")"; } } else { //それ以外を代入する代入文の関数 this.cc[ funcname ] = function( arg1 ) { this[ valuename ] = arg1; } } if( rgbaMatchRes ) c = rgbaMatchRes[ 1 ]; return 'cc\.' + funcname + '( ' + c + ' );'; }.bind( this ) ); //このreplaceにより、代入文は関数実行の形に直された。その実行される関数も定義された。 //以上複雑 //コメント文と描画命令(関数だけになってる)だけを抽出する。 s = s.match( /(^\s*\/\/[^-].*|cc\..+;)/mg ).join( "\n" ); //関数実行文をデータの形式へ書き換えていく。 s = s.replace( /cc./g, "[ \"" ); s = s.replace( /\( /g, "\", " ); s = s.replace( / \);/g, " \]," ); s = s.replace( /\(\);/g, "\" \]," ); //コメント文はデータの形式のパーツ名部分となる。 s = s.replace( /\/\/(.*)/g, "\],\n\"$1\" : \[" ); //余計なものを削除、必要なものを追加 s = s.replace( /\],/, "" ); s += "\n],"; s = "parts = {\n" + s + "\n}\n"; //data.partsに代入 data.parts = null; with( data ) { eval( s ); } //データにした結果を見る //alert( s ); return data; } App.prototype.check = function( o1, o2 ) { //モーフィングする2つのデータに問題がないかチェックする。 //モーフィングしたい2つのデータはお互いに同じパーツを持つことが必要で、 //また、パーツを描画する命令の並びは両者で同じでなければならない。 //check1 片方にあるパーツ名が、もう片方に無い。 for( let name in o1.parts ) { if( o2.parts[ name ] ) { } else { console.log( name, "false" ); return "どちらかで " + name + " が存在しない."; } } //check2 2つのデータで描画命令の並びが異なる。 for( let name in o1.parts ) { for( let i = 0; i < o1.parts[ name ].length; i++ ) { let inst1 = o1.parts[ name ][ i ][ 0 ]; let inst2 = o2.parts[ name ][ i ][ 0 ]; if( inst1 != inst2 ) { return name + " の " + i + " 番目\nobj1: " + inst1 + "\nobj2: " + inst2 + "\n異なっている."; } } } console.log( "check ok." ); return true; } App.prototype.makeAnms_beziermorph = function( o1, o2, limitMs ) { //2つのデータをモーフィングするアニメデータを返す /* アニメデータとは あるオブジェクトのメンバの値を、 現在値から指定値へと少しずつ変えていくようなアニメの設定値群 (群といっても6個だけ) */ let anms = new Array(); let komasuu = limitMs / this.timerMs; for( let name in o1.parts ) { let list1 = o1.parts[ name ]; let list2 = o2.parts[ name ]; for( let lineNum = 0; lineNum < list1.length; lineNum++ ) { let line1 = list1[ lineNum ]; let line2 = list2[ lineNum ]; for( let argNum = 1; argNum < line1.length; argNum++ ) { let arg1 = line1[ argNum ]; let arg2 = line2[ argNum ]; //check. 同じ値ならアニメの必要はないので次の引数比較へ if( arg1 == arg2 ) continue; //アニメを作成する let anm = new Object(); //アニメの設定値群(6個) anm.object = line1; //あるオブジェクトの anm.member = argNum; //メンバの値を anm.staValue = arg1; //現在値から anm.endValue = arg2; //指定値(データo2の同命令同引数の値)へ anm.addValue = ( arg2 - arg1 ) / komasuu; //少しずつ anm.endFlg = false; //終了チェック関数の定義 現在値と指定値の大小で異なる if( anm.staValue < anm.endValue ) anm.checker = function() { return this.object[ this.member ] >= this.endValue; }.bind( anm ); //bind()はその関数内の this が何なのかを指定する else anm.checker = function() { return this.object[ this.member ] <= this.endValue; }.bind( anm ); anms.push( anm ); }//for }//for }//for return anms; } App.prototype.start = function() { //指定秒後に1コマの処理を実行(アニメ) this.timerId = setTimeout( this.frame.bind( this ), this.timerMs ); } App.prototype.frame = function() { //setTimeoutから呼ばれる関数 1コマの処理 //各アニメを実行する(オブジェクトのメンバの値を少しずつ変更する) for( var i = 0; i < this.anms.length; i++ ) { var anm = this.anms[ i ]; with( anm ) { //check. すでに終了 if( endFlg ) continue; object[ member ] += addValue; //check. 終了かどうか if( checker() ) { //addValueを足すとendValueを少し超えることがあるので正確な値に直す。 object[ member ] = endValue; endFlg = true; if( 0 ) { //スライダで動かす際にanmsを参照するので削除しない //アニメをアニメ配列から削除する this.anms.splice( i, 1 ); i--; } } } } this.draw( this.cc ); this.start(); //指定秒後に次の1コマ } App.prototype.frameGoto = function( frameNum ) { //アニメではなく任意の1コマを描画する。 //スライダが動かされたときに呼ばれる。 for( var i = 0; i < this.anms.length; i++ ) { var anm = this.anms[ i ]; with( anm ) { object[ member ] = staValue + addValue * frameNum; //addValueを足すとendValueを少し超えることがあるので正確な値に直す。 if( checker() ) { object[ member ] = endValue; } } } this.draw( this.cc ); } App.prototype.draw = function( cc ) { cc.clearRect( 0, 0, this.cc.canvas.width, this.cc.canvas.height ); //2つのデータを表示 1にして試してよい。 console.log( this.sampleview ); if( this.sampleview ) { cc.canvas.width = 1024; cc.fillText( "sample1", 200, 40 ); cc.save(); cc.translate( 200, this.cc.canvas.height / 2 ); this.drawers[ 0 ]( this.cc ); cc.restore(); cc.fillText( "sample2", 800, 40 ); cc.save(); cc.translate( 800, this.cc.canvas.height / 2 ); this.drawers[ 1 ]( this.cc ); cc.restore(); } cc.save(); //画面中央を 0,0 にする。 cc.translate( this.cc.canvas.width / 2, this.cc.canvas.height / 2 ); var zSortedParts = Object.values( this.fromData.parts ); /* 将来、partsごとにzIndex値を用意し、 zIndex値で並べ替えることができるようにする予定。 パーツ同士の重なりの前後関係を変えられるようになる。 */ for( var j = 0; j < zSortedParts.length; j++ ) { var part = zSortedParts[ j ]; for( var i = 0; i < part.length; i++ ) { //partは描画の1パーツであり、複数の描画命令からなる。 //1つの描画命令は配列状になっている。 // [ パス描画関数名, その引数1, その引数2, ... ]; //これを以下のように関数として実行する。 // パス描画関数名( その引数1, その引数2, ... ); //配列状になっている var funcname = part[ i ][ 0 ]; var args = part[ i ].slice( 1 ); //関数として実行する cc[ funcname ].apply( cc, args ); //applyは指定の配列を関数の引数の並びに置き換えて関数を実行する //第1引数は関数内の this が何なのかを指定 } } cc.restore(); //save, restoreはtranslateを使っているから。 /* translate や rotate などで canvas の描画設定を変更したいとき、 事前に、その前の描画設定を save で保管しておく。 そのうえで translate や rotate などで新しい描画設定を行って描画する。 新しい描画設定での描画が終わったら restore で保管しておいた元の描画設定に戻す。 そうしないと、translate や rotate は変更の上から変更を重ねてしまい、 おかしな描画になり、収拾がつかなくなる。 */ } //以上プログラム //以下はデータ //---モーフィングしたいデータ uma //これら関数の記述には一定の規則が要求されているので注意。 //規則の説明は現在行っていない。 //でもちょっと(親切ではありませんが)説明↓ //2つのデータ(以下の2つの関数)は、まったく同一の描画命令とコメントが並ぶが、 //描画命令の引数の数値のみ異なっている、というもの。 //コメント//---path~//---/pathで囲まれた部分が有効。 //コメントだけの行は以降の行を1つのパーツとし、名前を付ける。 //cc.で始まる描画命令だけを書くことができる。 //cc.lineWidth = xx;などの代入文は、数値と"rgba(..)"の代入のみ対応。 //"rgb(..)"、"red"等の代入は対応していない。以下のようなfontの記述も対応していない。 //cc.font = "14px 'MS ゴシック'"; //対応しているのは、数値と、"rgba(..)"だけ。 //その他、綿密に考えていないのであしからず。 App.draw_uma = function( cc ) { //---path //migi tuno cc.save(); cc.translate( 100, 50 ); cc.lineWidth = 1; cc.strokeStyle = "rgba(0,0,0,1)"; cc.fillStyle = "rgba(245,230,210,1)"; cc.beginPath(); cc.moveTo( -57, -81 ); cc.bezierCurveTo( -65, -87, -85, -88, -90, -88 ); cc.bezierCurveTo( -100, -92, -115, -90, -125, -89 ); cc.bezierCurveTo( -139, -88, -134, -79, -127, -77 ); cc.lineTo( -102, -62 ); cc.bezierCurveTo( -96, -55, -97, -56, -79, -47 ); cc.fill(); cc.stroke(); cc.restore(); //hidari tuno cc.save(); cc.translate( -100, 50 ); cc.lineWidth = 1; cc.strokeStyle = "rgba(0,0,0,0)"; cc.fillStyle = "rgba(245,230,210,0)"; cc.beginPath(); cc.moveTo( 71, -86 ); cc.bezierCurveTo( 71, -86, 92, -89, 92, -89 ); cc.bezierCurveTo( 102, -90, 100, -91, 114, -89 ); cc.lineTo( 127, -88 ); cc.bezierCurveTo( 137, -90, 141, -78, 133, -76 ); cc.bezierCurveTo( 115, -66, 105, -53, 90, -48 ); cc.fill(); cc.stroke(); cc.restore(); //migi mimi cc.lineWidth = 1; cc.strokeStyle = "rgba(0,0,0,1)"; cc.fillStyle = "rgba(115,71,33,1)"; cc.beginPath(); cc.moveTo( -4, -116 ); cc.bezierCurveTo( 2, -125, 4, -148, -10, -159 ); cc.bezierCurveTo( -18, -167, -25, -175, -33, -191 ); cc.bezierCurveTo( -46, -152, -42, -118, -28, -99 ); cc.fill(); cc.stroke(); cc.beginPath(); cc.moveTo( -40.5, -141 ); cc.bezierCurveTo( -40, -164, -31, -174, -33, -191 ); cc.stroke(); //ha cc.save(); cc.translate( 0, 0 ); cc.lineWidth = 1; cc.strokeStyle = "rgba(0,0,0,1)"; cc.fillStyle = "rgba(255,230,200,1)"; //ha sita cc.beginPath(); cc.moveTo( -25, 199 ); cc.lineTo( -18, 205 ); cc.lineTo( -1, 207 ); cc.lineTo( -6, 199 ); cc.fill(); cc.stroke(); cc.beginPath(); cc.moveTo( -20, 199 ); cc.lineTo( -10, 208 ); cc.lineTo( -1, 207 ); cc.lineTo( -6, 199 ); cc.fill(); cc.stroke(); cc.beginPath(); cc.moveTo( 3, 210 ); cc.lineTo( -9, 200 ); cc.lineTo( 1, 196 ); cc.lineTo( 10, 204 ); cc.fill(); cc.stroke(); cc.beginPath(); cc.moveTo( 10, 204 ); cc.lineTo( 2, 196 ); cc.lineTo( 11, 185 ); cc.lineTo( 20, 195 ); cc.fill(); cc.stroke(); cc.beginPath(); cc.moveTo( 20, 195 ); cc.lineTo( 11, 185 ); cc.lineTo( 21, 176 ); cc.lineTo( 27, 182 ); cc.fill(); cc.stroke(); cc.beginPath(); cc.moveTo( 27, 182 ); cc.lineTo( 21, 176 ); cc.lineTo( 33, 159 ); cc.fill(); cc.stroke(); //ha ue left cc.beginPath(); cc.moveTo( 25, 154 ); cc.lineTo( 28, 165 ); cc.lineTo( 36, 152 ); cc.lineTo( 36, 137 ); cc.fill(); cc.stroke(); cc.beginPath(); cc.moveTo( 16, 168 ); cc.lineTo( 21, 177 ); cc.lineTo( 28, 165 ); cc.lineTo( 25, 154 ); cc.fill(); cc.stroke(); cc.beginPath(); cc.moveTo( 6, 178 ); cc.lineTo( 13, 188 ); cc.lineTo( 21, 177 ); cc.lineTo( 16, 168 ); cc.fill(); cc.stroke(); //ha ue right cc.beginPath(); cc.moveTo( -56, 183 ); cc.bezierCurveTo( -47, 193, -44, 195, -29, 197 ); cc.lineTo( -36, 184 ); cc.fill(); cc.stroke(); cc.beginPath(); cc.moveTo( -39, 185 ); cc.bezierCurveTo( -37, 192, -29, 201, -23, 200 ); cc.lineTo( -11, 202 ); cc.lineTo( -7, 185 ); cc.fill(); cc.stroke(); cc.beginPath(); cc.moveTo( -25, 185 ); cc.bezierCurveTo( -23, 192, -18, 198, -15, 200 ); cc.bezierCurveTo( -10, 205, 2, 199, 3, 198 ); cc.lineTo( -7, 186 ); cc.fill(); cc.stroke(); //ha ue center cc.beginPath(); //p cc.moveTo( -9, 186 ); cc.bezierCurveTo( -6, 196, 2, 199, 5, 196 ); cc.lineTo( 13, 188 ); cc.lineTo( 6, 178 ); cc.fill(); cc.stroke(); cc.restore(); //rinkaku cc.lineWidth = 1; cc.strokeStyle = "rgba(0,0,0,1)"; cc.fillStyle = "rgba(115,71,33,1)"; cc.beginPath(); cc.moveTo( 213, -5 ); cc.bezierCurveTo( 143, -122, 36, -157, -2, -105 ); cc.bezierCurveTo( -39, -102, -51, -45, -59, -12 ); cc.bezierCurveTo( -53, 4, -56, 17, -60, 31 ); cc.lineTo( -79, 104 ); cc.lineTo( -79, 104 ); cc.bezierCurveTo( -93, 141, -89, 184, -53, 184 ); cc.bezierCurveTo( -53, 184, -9, 186, -9, 186 ); cc.bezierCurveTo( 5, 186, 27, 157, 35, 136 ); //p cc.bezierCurveTo( 35, 136, 28, 180, 26, 183 ); cc.bezierCurveTo( 23, 193, 10, 207, 1, 209 );//p2 cc.bezierCurveTo( 6, 214, 13, 214, 19, 212 ); cc.bezierCurveTo( 27, 216, 39, 214, 42, 205 ); cc.bezierCurveTo( 46, 193, 58, 130, 61, 110 );//p3 cc.bezierCurveTo( 70, 110, 77, 105, 88, 100 ); cc.bezierCurveTo( 103, 94, 105, 90, 110, 69 ); cc.fill(); cc.stroke(); //hidari mimi cc.lineWidth = 1; cc.strokeStyle = "rgba(0,0,0,1)"; cc.fillStyle = "rgba(115,71,33,1)"; cc.beginPath(); cc.moveTo( 53, -110 ); cc.bezierCurveTo( 40, -150, 63, -164, 64, -188 ); cc.bezierCurveTo( 72, -180, 76, -173, 80, -161 ); cc.bezierCurveTo( 85, -151, 87, -138, 92, -126 ); cc.bezierCurveTo( 102, -108, 100, -75, 75, -65 ); cc.fill(); cc.stroke(); cc.beginPath(); cc.moveTo( 81, -87 ); cc.bezierCurveTo( 97, -90, 88, -123, 83, -143 ); cc.stroke(); //migime cc.lineWidth = 4; cc.beginPath(); cc.moveTo( 50, -10 ); cc.lineTo( 50, 30 ); cc.closePath(); cc.stroke(); //hidarime cc.lineWidth = 4; cc.beginPath(); cc.moveTo( -50, -15 ); cc.lineTo( -50, 20 ); cc.closePath(); cc.stroke(); //kami cc.lineWidth = 1; cc.strokeStyle = "rgba(0,0,0,1)"; cc.fillStyle = "rgba(60,30,6,1)"; cc.beginPath(); cc.moveTo( 50, -131 ); cc.bezierCurveTo( 15, -147, -33, -122, -53, -85 ); cc.bezierCurveTo( -53, -85, -30, -102, -30, -102 ); cc.bezierCurveTo( -30, -102, -49, -57, -49, -57 ); cc.bezierCurveTo( -49, -57, -20, -82, -20, -82 ); cc.bezierCurveTo( -20, -82, -30, -37, -30, -37 ); cc.bezierCurveTo( -30, -37, 1, -78, 1, -78 ); cc.bezierCurveTo( 1, -78, 1, -15, 1, -15 ); cc.bezierCurveTo( 1, -15, 21, -68, 21, -68 ); cc.bezierCurveTo( 21, -68, 35, -34, 35, -34 ); cc.bezierCurveTo( 35, -34, 40, -66, 40, -66 ); cc.bezierCurveTo( 40, -66, 48, -51, 48, -51 ); cc.bezierCurveTo( 48, -51, 48, -69, 48, -69 ); cc.bezierCurveTo( 48, -69, 66, -56, 66, -56 ); cc.bezierCurveTo( 66, -56, 49, -113, 49, -113 ); cc.fill(); cc.stroke(); //hana cc.lineWidth = 1; cc.strokeStyle = "rgba(0,0,0,0)"; cc.fillStyle = "rgba(50,35,25,0.95)"; cc.beginPath(); cc.moveTo( -59, 183 ); cc.bezierCurveTo( -95, 174, -95, 144, -87, 125 ); cc.bezierCurveTo( -72, 123, -70, 128, -74, 148 );//c cc.bezierCurveTo( -73, 158, -63, 154, -45, 154 );//c cc.bezierCurveTo( -37, 153, -35, 141, -36, 132 ); cc.bezierCurveTo( -34, 128, -32, 128, -32, 128 ); cc.bezierCurveTo( -36, 128, -3, 127, -3, 127 ); cc.bezierCurveTo( 10, 125, 13, 151, 13, 150 ); cc.bezierCurveTo( 13, 160, 0, 161, -3, 174 ); cc.bezierCurveTo( 5, 172, 15, 168, 22, 159 ); cc.bezierCurveTo( 16, 172, 6, 183, -10, 186 ); cc.fill(); cc.stroke(); //migi hana ana cc.lineWidth = 1; cc.strokeStyle = "rgba(0,0,0,1)"; cc.beginPath(); cc.moveTo( -92, 136 ); cc.bezierCurveTo( -85, 131, -81, 133, -78, 137 ); cc.bezierCurveTo( -81, 145, -90, 163, -72, 171 ); cc.stroke(); //hidari hana ana cc.lineWidth = 1; cc.strokeStyle = "rgba(0,0,0,1)"; cc.beginPath(); cc.moveTo( 1, 141 ); cc.bezierCurveTo( -6, 135, -15, 135, -24, 140 ); cc.bezierCurveTo( -18, 148, -19, 164, -28, 174 ); cc.stroke(); //hanawa cc.save(); cc.scale( 2, 2 ); cc.translate( 13, -40 ); cc.lineWidth = 1; cc.strokeStyle = "rgba(0,0,0,0)"; cc.fillStyle = "rgba(255,255,50,0)"; cc.beginPath(); cc.moveTo( -59, 111 ); cc.bezierCurveTo( -100, 123, -100, 185, -79, 198 ); cc.bezierCurveTo( -61, 215, -13, 220, 9, 195 ); cc.bezierCurveTo( 30, 170, 22, 115, -21, 111 ); cc.bezierCurveTo( -24, 111, -30, 123, -29, 123 ); cc.bezierCurveTo( 8, 120, 16, 170, -1, 187 ); cc.bezierCurveTo( -18, 207, -58, 198, -67, 185 ); cc.bezierCurveTo( -90, 163, -75, 122, -49, 120 ); cc.bezierCurveTo( -49, 116, -49, 110, -59, 111 ); cc.fill(); cc.stroke(); cc.restore(); //---/path } //---モーフィングしたいデータ usi //これら関数の記述には一定の規則が要求されているので注意。 //規則の説明は現在行っていない。 App.draw_usi = function( cc ) { //---path //migi tuno cc.save(); cc.translate( 0, 0 ); cc.lineWidth = 1; cc.strokeStyle = "rgba(0,0,0,1)"; cc.fillStyle = "rgba(245,230,210,1)"; cc.beginPath(); cc.moveTo( -57, -81 ); cc.bezierCurveTo( -65, -87, -85, -88, -90, -88 ); cc.bezierCurveTo( -100, -92, -115, -90, -125, -89 ); cc.bezierCurveTo( -139, -88, -134, -79, -127, -77 ); cc.lineTo( -102, -62 ); cc.bezierCurveTo( -96, -55, -97, -56, -79, -47 ); cc.fill(); cc.stroke(); cc.restore(); //hidari tuno cc.save(); cc.translate( 0, 0 ); cc.lineWidth = 1; cc.strokeStyle = "rgba(0,0,0,1)"; cc.fillStyle = "rgba(245,230,210,1)"; cc.beginPath(); cc.moveTo( 71, -86 ); cc.bezierCurveTo( 71, -86, 92, -89, 92, -89 ); cc.bezierCurveTo( 102, -90, 100, -91, 114, -89 ); cc.lineTo( 127, -88 ); cc.bezierCurveTo( 137, -90, 141, -78, 133, -76 ); cc.bezierCurveTo( 115, -66, 105, -53, 90, -48 ); cc.fill(); cc.stroke(); cc.restore(); //migi mimi cc.lineWidth = 1; cc.strokeStyle = "rgba(0,0,0,1)"; cc.fillStyle = "rgba(196,143,69,1)"; cc.beginPath(); cc.moveTo( -81, -39 ); cc.bezierCurveTo( -85, -55, -107, -50, -129, -46 ); cc.bezierCurveTo( -175, -45, -144, 0, -107, 4 ); cc.bezierCurveTo( -100, 6, -90, 0, -83, -7 ); cc.fill(); cc.stroke(); cc.beginPath(); cc.moveTo( -91, -23 ); cc.bezierCurveTo( -95, -38, -132, -41, -136, -30 ); cc.stroke(); //ha cc.save(); cc.translate( 0, -100 ); cc.lineWidth = 1; cc.strokeStyle = "rgba(0,0,0,0)"; cc.fillStyle = "rgba(255,255,255,0)"; //ha sita cc.beginPath(); cc.moveTo( -25, 199 ); cc.lineTo( -18, 205 ); cc.lineTo( -1, 207 ); cc.lineTo( -6, 199 ); cc.fill(); cc.stroke(); cc.beginPath(); cc.moveTo( -20, 199 ); cc.lineTo( -10, 208 ); cc.lineTo( -1, 207 ); cc.lineTo( -6, 199 ); cc.fill(); cc.stroke(); cc.beginPath(); cc.moveTo( 3, 210 ); cc.lineTo( -9, 200 ); cc.lineTo( 1, 196 ); cc.lineTo( 10, 204 ); cc.fill(); cc.stroke(); cc.beginPath(); cc.moveTo( 10, 204 ); cc.lineTo( 2, 196 ); cc.lineTo( 11, 185 ); cc.lineTo( 20, 195 ); cc.fill(); cc.stroke(); cc.beginPath(); cc.moveTo( 20, 195 ); cc.lineTo( 11, 185 ); cc.lineTo( 21, 176 ); cc.lineTo( 27, 182 ); cc.fill(); cc.stroke(); cc.beginPath(); cc.moveTo( 27, 182 ); cc.lineTo( 21, 176 ); cc.lineTo( 33, 159 ); cc.fill(); cc.stroke(); //ha ue left cc.beginPath(); cc.moveTo( 25, 154 ); cc.lineTo( 28, 165 ); cc.lineTo( 36, 152 ); cc.lineTo( 36, 137 ); cc.fill(); cc.stroke(); cc.beginPath(); cc.moveTo( 16, 168 ); cc.lineTo( 21, 177 ); cc.lineTo( 28, 165 ); cc.lineTo( 25, 154 ); cc.fill(); cc.stroke(); cc.beginPath(); cc.moveTo( 6, 178 ); cc.lineTo( 13, 188 ); cc.lineTo( 21, 177 ); cc.lineTo( 16, 168 ); cc.fill(); cc.stroke(); //ha ue right cc.beginPath(); cc.moveTo( -56, 183 ); cc.bezierCurveTo( -47, 193, -44, 195, -29, 197 ); cc.lineTo( -36, 184 ); cc.fill(); cc.stroke(); cc.beginPath(); cc.moveTo( -39, 185 ); cc.bezierCurveTo( -37, 192, -29, 201, -23, 200 ); cc.lineTo( -11, 202 ); cc.lineTo( -7, 185 ); cc.fill(); cc.stroke(); cc.beginPath(); cc.moveTo( -25, 185 ); cc.bezierCurveTo( -23, 192, -18, 198, -15, 200 ); cc.bezierCurveTo( -10, 205, 2, 199, 3, 198 ); cc.lineTo( -7, 186 ); cc.fill(); cc.stroke(); //ha ue center cc.beginPath(); //p cc.moveTo( -9, 186 ); cc.bezierCurveTo( -6, 196, 2, 199, 5, 196 ); cc.lineTo( 13, 188 ); cc.lineTo( 6, 178 ); cc.fill(); cc.stroke(); cc.restore(); //rinkaku cc.lineWidth = 1; cc.strokeStyle = "rgba(0,0,0,1)"; cc.fillStyle = "rgba(196,143,69,1)"; cc.beginPath(); cc.moveTo( 60, 115 ); cc.bezierCurveTo( 110, 51, 90, 2, 93, -25 ); cc.bezierCurveTo( 90, -70, 75, -90, 0, -90 ); cc.bezierCurveTo( -50, -90, -75, -80, -80, -50 ); cc.lineTo( -85, 20 ); cc.lineTo( -96, 50 ); cc.bezierCurveTo( -110, 80, -100, 100, -87, 120 ); cc.bezierCurveTo( -80, 130, -70, 140, -55, 150 ); cc.bezierCurveTo( 0, 150, 40, 140, 40, 123 );//p cc.bezierCurveTo( 40, 123, 40, 123, 40, 123 ); cc.bezierCurveTo( 40, 140, 0, 150, -55, 150 );//p2 cc.bezierCurveTo( -55, 150, -55, 150, -55, 150 ); cc.bezierCurveTo( -55, 150, -55, 150, -55, 150 ); cc.bezierCurveTo( -20, 170, 39, 164, 60, 115 );//p3 cc.bezierCurveTo( 60, 115, 60, 115, 60, 115 ); cc.bezierCurveTo( 60, 115, 60, 115, 60, 115 ); cc.fill(); cc.stroke(); //hidari mimi cc.lineWidth = 1; cc.strokeStyle = "rgba(0,0,0,1)"; cc.fillStyle = "rgba(196,143,69,1)"; cc.beginPath(); cc.moveTo( 90, -32 ); cc.bezierCurveTo( 123, -50, 145, -50, 161, -44 ); cc.bezierCurveTo( 180, -40, 185, -30, 182, -24 ); cc.bezierCurveTo( 170, -6, 144, 18, 126, 20 ); cc.bezierCurveTo( 112, 20, 104, 16, 92, 2 ); cc.fill(); cc.stroke(); cc.beginPath(); cc.moveTo( 112, -15 ); cc.bezierCurveTo( 103, -27, 121, -38, 151, -33 ); cc.stroke(); //migime cc.lineWidth = 4; cc.beginPath(); cc.moveTo( 50, -10 ); cc.lineTo( 50, 30 ); cc.closePath(); cc.stroke(); //hidarime cc.lineWidth = 4; cc.beginPath(); cc.moveTo( -50, -15 ); cc.lineTo( -50, 20 ); cc.closePath(); cc.stroke(); //kami cc.lineWidth = 1; cc.strokeStyle = "rgba(0,0,0,1)"; cc.fillStyle = "rgba(186,133,59,1)"; cc.beginPath(); cc.moveTo( 54, -93 ); cc.bezierCurveTo( 53, -102, 30, -98, 30, -96 ); cc.bezierCurveTo( 20, -103, 0, -110, -9, -100 ); cc.bezierCurveTo( -13, -104, -27, -101, -33, -92 ); cc.bezierCurveTo( -34, -97, -50, -95, -51, -89 ); cc.bezierCurveTo( -70, -95, -66, -70, -77, -64 ); cc.bezierCurveTo( -68, -75, -50, -83, -43, -70 ); cc.bezierCurveTo( -43, -70, -43, -70, -43, -70 );//dummy cc.bezierCurveTo( -35, -81, -9, -79, 0, -70 ); cc.bezierCurveTo( 10, -66, 14, -91, 42, -77 ); cc.bezierCurveTo( 42, -77, 42, -77, 42, -77 ); //dummy cc.bezierCurveTo( 44, -85, 60, -77, 58, -77 ); cc.bezierCurveTo( 65, -86, 72, -75, 81, -66 ); cc.bezierCurveTo( 81, -66, 84, -70, 84, -70 ); cc.bezierCurveTo( 77, -83, 63, -110, 54, -93 ); cc.fill(); cc.stroke(); //hana cc.lineWidth = 1; cc.strokeStyle = "rgba(0,0,0,1)"; cc.fillStyle = "rgba(50,50,50,1)"; cc.beginPath(); cc.moveTo( -43, 140 ); cc.bezierCurveTo( -43, 140, -65, 137, -68, 127 ); cc.bezierCurveTo( -70, 127, -82, 99, -62, 97 ); cc.bezierCurveTo( -57, 97, -40, 106, -33, 105 ); //c cc.bezierCurveTo( -23, 105, -3, 95, 3, 106 ); cc.bezierCurveTo( 8, 114, 6, 129, -3, 138 ); cc.bezierCurveTo( -3, 138, -3, 138, -3, 138 ); cc.bezierCurveTo( -3, 138, -3, 138, -3, 138 ); cc.bezierCurveTo( -3, 138, -3, 138, -3, 138 ); cc.bezierCurveTo( -3, 138, -3, 138, -3, 138 ); cc.bezierCurveTo( -3, 138, -3, 138, -3, 138 ); cc.fill(); cc.stroke(); //migi hana ana cc.lineWidth = 1; cc.strokeStyle = "rgba(0,0,0,1)"; cc.beginPath(); cc.moveTo( -59, 110 ); cc.bezierCurveTo( -45, 109, -45, 132, -60, 130 ); cc.bezierCurveTo( -60, 130, -60, 130, -60, 130 ); cc.stroke(); //hidari hana ana cc.lineWidth = 1; cc.strokeStyle = "rgba(0,0,0,1)"; cc.beginPath(); cc.moveTo( -11, 109 ); cc.bezierCurveTo( -31, 109, -33, 133, -23, 133 ); cc.bezierCurveTo( -23, 133, -23, 133, -23, 133 ); cc.stroke(); //hanawa cc.save(); cc.scale( 1, 1 ); cc.translate( 0, 0 ); cc.lineWidth = 1; cc.strokeStyle = "rgba(0,0,0,1)"; cc.fillStyle = "rgba(255,255,50,1)"; cc.beginPath(); cc.moveTo( -59, 111 ); cc.bezierCurveTo( -100, 123, -100, 185, -79, 198 ); cc.bezierCurveTo( -61, 215, -13, 220, 9, 195 ); cc.bezierCurveTo( 30, 170, 22, 115, -21, 111 ); cc.bezierCurveTo( -24, 111, -30, 123, -29, 123 ); cc.bezierCurveTo( 8, 120, 16, 170, -1, 187 ); cc.bezierCurveTo( -18, 207, -58, 198, -67, 185 ); cc.bezierCurveTo( -90, 163, -75, 122, -49, 120 ); cc.bezierCurveTo( -49, 116, -49, 110, -59, 111 ); cc.fill(); cc.stroke(); cc.restore(); //---/path }