9/29に書いたブログに載せてたJSFLがきちんと親のアニメーションと子のアニメーションを合わせたものになってくれないことがありました。
今考えたら当たり前なんですが、それまでは単純に親と子の移動、回転、スケール、スキューを足したり掛けたりしていました。
これでは、親にスキューかかってて子が回転していた場合、スキューかかった平行四辺形のまま回転するというどうしようもない感じになってしまいました。
そこでどうすればいいのだろうと悩みながらFlash(jsfl)のリファレンスをいろいろ眺めていました。
すると、通常の移動、回転、スケール、スキュー以外に変換に使えそうなのを見つけました。
それがマトリクス(行列)でした!
下記のページを見ると・・・
Adobe Flash Professional * Matrix オブジェクトの概要
http://help.adobe.com/ja_JP/flash/cs/extend/WSd6d4f896b3a8801bc44625813cb587665d-8000.html
matrix.a 変換マトリックス内の (0,0) エレメントを指定する浮動小数点値。
matrix.b 変換マトリックス内の (0,1) エレメントを指定する浮動小数点値。
matrix.c 変換マトリックス内の (1,0) エレメントを指定する浮動小数点値。
matrix.d 変換マトリックス内の (1.1) エレメントを指定する浮動小数点値。
matrix.tx シンボルの基準点またはシェイプの中心の x 軸の位置を指定する浮動小数点値。
matrix.ty シンボルの基準点またはシェイプの中心の y 軸の位置を指定する浮動小数点値。
そして、これを3x3の行列で表すとこうなるそうです。(ASだけど下記のサイト参考)
|a c tx|
|b d ty|
|0 0 1|
行列?なにそれ?おいしいの? | Creators MeetUp vol. 20
http://fumiononaka.com/Sample/Creators_MeetUp/Creators_MeetUp_140920.html
この親と子の行列をかけ合わせると想定通りの動きになりました。
こういうの2次元アフィン変換っていうんですかね?(まだ良くわかってない)
ご興味あれば使ってみてください。
使い方は前回の記事をご覧ください。
zxpファイルのDLはこちらから
//fl.trace("Flashのバージョン " + fl.version); //CS5 =WIN 11,0,2,489 var doc = fl.getDocumentDOM(); var P_TL = doc.getTimeline(); var selectedLayers = P_TL.getSelectedLayers(); //fl.trace("selectedLayers.lengthは " + selectedLayers.length); //fl.trace("Doc" + fl.findDocumentIndex(fl.documents[0].name)); var openDocs = fl.documents; for(a=0; a < openDocs.length; a++){ //fl.trace(i + " " + openDocs[a].name +"\n"); if (openDocs[a].name.indexOf ("_copy") != -1){ var copyDocIdx = fl.findDocumentIndex(openDocs[a].name); fl.closeDocument(fl.documents[copyDocIdx ] , false); fl.trace("開かれていたコピーを閉じました"); } } if (selectedLayers.length == 0) { alert("何も選択されていません"); }else{ //-----念の為、ファイルをコピーしておく fileCopy (); //-----選択している親レイヤーの名前を入れていく配列 var P_LayerNameArr = []; var selLayLen = selectedLayers.length; for (g = 0; g < selLayLen ; g++ ){ var P_LayerName = P_TL.layers[ selectedLayers[ g ] ].name; P_LayerNameArr.push( P_LayerName ); } //fl.trace("選択したレイヤーの名前の配列は " + P_LayerNameArr); for (h = 0; h < selectedLayers.length ; h++){ //-----選択しているシンボルを解除しておく doc.selectNone(); var P_LayerIdx= P_TL.findLayerIndex( P_LayerNameArr[ h ] ); //fl.trace("P_LayerIdxは " + P_LayerIdx[ 0 ] + " : 現在のレイヤーネームは " + P_TL.layers[ P_LayerIdx[ 0 ] ].name); P_TL.setSelectedLayers( P_LayerIdx[ 0 ] ,true); //-----選択したレイヤーがロックされていたらエラーになるのでロック外す P_TL.setLayerProperty('locked', false); var P_FrameArray = P_TL.layers[ P_LayerIdx[ 0 ] ].frames; var P_LastFrame = P_FrameArray.length ; //P_TL.frameCount; //fl.trace("P_LastFrameは " + P_LastFrame); //-----コンバート前に初期のキーフレームを配列に入れておく var P_keyframeArry = []; for (k = 0; k < P_LastFrame; k++){ var frame = P_FrameArray[ k ]; var firstFrameElement = P_TL.layers[ P_LayerIdx[ 0 ] ].frames[ k ].elements; if (k == frame.startFrame && firstFrameElement.length != 0 ) { P_keyframeArry.push( k ); } } //fl.trace(P_keyframeArry); //-----キーフレームのある配列の最大値(一番最後のフレーム)を取得して、タイムラインのカウント数より小さい場合書き換える //-----※配列の中では0始まりになっているので+1する var P_maxKeyFrame = Math.max.apply( null, P_keyframeArry ) + 1; if ( P_maxKeyFrame < P_LastFrame){ //fl.trace("書き換えました" + P_LastFrame + " >> "+ P_maxKeyFrame); P_LastFrame = P_maxKeyFrame; } //fl.trace("キーフレーム配列(P_keyframeArry)" + P_keyframeArry); //fl.trace("P_keyframeArry.lengthは" + P_keyframeArry.length); //-----最初のキーフレームから最後のキーフレームまでのフレーム選択して、キーフレーム変換 var P_minKeyFrame = Math.min.apply( null, P_keyframeArry ); P_TL.setSelectedFrames( P_minKeyFrame , P_LastFrame - 1 ); //fl.trace("親の最初と最後のフレーム " + P_minKeyFrame + " : "+ P_LastFrame); P_TL.convertToKeyframes(); //-----各フレームの情報を入れていく配列を用意 var arrP_Alp = new Array(); var arrP_Rot = new Array(); var arrP_SclX = new Array(); var arrP_SclY = new Array(); var arrP_SkwX = new Array(); var arrP_SkwY = new Array(); var arrP_PosX = new Array(); var arrP_PosY = new Array(); var arrP_Mat_a = new Array(); var arrP_Mat_b = new Array(); var arrP_Mat_c = new Array(); var arrP_Mat_d = new Array(); var arrP_Mat_tx = new Array(); var arrP_Mat_ty = new Array(); var P_blankFrames = new Array(); //fl.trace("P_LastFrame = " + P_LastFrame); for (i=0 ; i < P_LastFrame; i++) { P_TL.currentFrame = i; var frame1 = P_TL.layers[ P_LayerIdx[ 0 ] ].frames[ i ]; var curFrameElement1 = P_TL.layers[ P_LayerIdx[ 0 ] ].frames[ i ].elements; //fl.trace("curFrameElement1.lengthは " + curFrameElement1.length); //-----各フレームをまわしていき、空のフレームじゃなかったら親の回転・スケール・スキュー・移動を格納していく if ( !frame1.isEmpty && curFrameElement1.length != 0){ //fl.trace("i = " + i); var elm1 = P_TL.layers[ P_LayerIdx[ 0 ] ].frames[ i ].elements[ 0 ]; elm1.selected = true; arrP_Alp.push( elm1.colorAlphaPercent ); if ( !isNaN(elm1.rotation) ){ //fl.trace("NaNじゃない"); arrP_Rot.push( elm1.rotation ); }else{ //fl.trace("NaNやん"); arrP_Rot.push( 0 ); } //fl.trace("親の回転は " + elm1.rotation ) arrP_SclX.push( elm1.scaleX ); arrP_SclY.push( elm1.scaleY ); arrP_SkwX.push( elm1.skewX ); arrP_SkwY.push( elm1.skewY ); arrP_PosX.push( elm1.x ); arrP_PosY.push( elm1.y ); arrP_Mat_a.push( elm1.matrix.a ); arrP_Mat_b.push( elm1.matrix.b ); arrP_Mat_c.push( elm1.matrix.c ); arrP_Mat_d.push( elm1.matrix.d ); arrP_Mat_tx.push( elm1.matrix.tx ); arrP_Mat_ty.push( elm1.matrix.ty ); //fl.trace( i + " : arrP_PosX = " + elm1.x ); //fl.trace( i + " : arrP_PosY = " + elm1.y ); }else { //親の空のフレームの場所をいれていく P_blankFrames.push( i ); arrP_Alp.push( 0 ); arrP_Rot.push( 0 ); arrP_SclX.push( 1 ); arrP_SclY.push( 1 ); arrP_SkwX.push( 0 ); arrP_SkwY.push( 0 ); arrP_PosX.push( 0 ); arrP_PosY.push( 0 ); arrP_Mat_a.push( 1 ); arrP_Mat_b.push( 0 ); arrP_Mat_c.push( 0 ); arrP_Mat_d.push( 1 ); arrP_Mat_tx.push( 0 ); arrP_Mat_ty.push( 0 ); } } //fl.trace("P_blankFramesは " + P_blankFrames); //-----現在のレイヤーの最初のキーフレームにあるエレメントを選択状態にしておく P_TL.currentFrame = P_minKeyFrame; var elm = P_TL.layers[ P_LayerIdx[ 0 ] ].frames[ P_minKeyFrame ].elements; //fl.trace("elm.lengthは " + elm.length + ": エレメントタイプは" + elm[ 0 ].elementType + " , ネームは " + elm[ 0 ].libraryItem.name); elm[ 0 ].selected = true; //------------------------------------------------------------------子の階層に入る---------------------------------------------------------------------------------------- doc.enterEditMode('inPlace'); //-----子の階層のタイムラインを取得しておく var C_TL = doc.getTimeline(); var C_layerCount = C_TL.layerCount; //fl.trace("C_Countは " + C_Count); //-----インスタンスのタイプがシンボルのレイヤーのインデックスを入れていく配列 var C_LayerArray = new Array(); //-----子どものフレームの配列を入れておく var C_keyframeArry = new Array(); //-----子どものレイヤーの名前を入れていく配列 var C_LayerNameArr = new Array(); //-----子どもの空フレームを入れる配列 var C_blankFrames = new Array(); for (f = 0; f < C_layerCount ; f++ ){ C_keyframeArry[ f ] = new Array(); var C_FrameArray1 = C_TL.layers[ f ].frames; var C_LayerName = C_TL.layers[ f ].name; //fl.trace("C_FrameArray1.lengthは " + C_FrameArray1.length); //-----キーフレームのあるフレームをC_keyframeArryに入れていく var C_FrmArry1Len = C_FrameArray1.length; for (j = 0; j < C_FrmArry1Len ; j++){ var frame2 = C_FrameArray1[ j ]; var firstFrame = C_TL.layers[ f ].frames[ j ]; if (j == frame2.startFrame && firstFrame.elements.length != 0 ){ C_keyframeArry[ f ] .push( j ); //fl.trace("jは " + j); } } //-----シンボルのあるレイヤーの名前を if (C_keyframeArry[ f ] .length > 1) { var C_minKeyFrame = Math.min.apply( null, C_keyframeArry [ f ] ); var insType = C_TL.layers[ f ].frames[ C_minKeyFrame ].elements[ 0 ].instanceType; if (insType == "symbol" ){ C_LayerNameArr.push( C_LayerName ); } } //fl.trace(" f は " + f + " : " + " C_keyframeArry[ f ] は " + C_keyframeArry[ f ] + " : " + "C_keyframeArry[ f ].lengthは " +C_keyframeArry[ f ].length); } //fl.trace("子どものレイヤーの名前の配列は " + C_LayerNameArr); //-----各フレームの情報を入れていく配列を用意 var arrC_Alp = new Array(); var arrC_Rot = new Array(); var arrC_SclX = new Array(); var arrC_SclY = new Array(); var arrC_SkwX = new Array(); var arrC_SkwY = new Array(); var arrC_PosX = new Array(); var arrC_PosY = new Array(); var arrC_Mat_a = new Array(); var arrC_Mat_b = new Array(); var arrC_Mat_c = new Array(); var arrC_Mat_d = new Array(); var arrC_Mat_tx = new Array(); var arrC_Mat_ty = new Array(); var C_LayNmArrLen = C_LayerNameArr.length; for (b=0; b < C_LayNmArrLen ; b++){ //-----C_LayerNameArrに格納してあるレイヤーの名前からそのレイヤーのインデックスを取得する var C_LayerIdx = C_TL.findLayerIndex( C_LayerNameArr[ b ] ); C_TL.setSelectedLayers( C_LayerIdx[ 0 ] ); //-----レイヤーがロックされていたらエラーになるのでロック外す C_TL.setLayerProperty('locked', false); var C_LastFrame1 = C_TL.layers[ C_LayerIdx[ 0 ] ].frames.length; //fl.trace("C_LastFrame1は " + C_LastFrame1); //var C_maxKeyFrame = Math.min.apply( null, C_keyframeArry [ f ] ); //-----今処理中の子のレイヤーの名前を取得 var C_LayerName = C_TL.layers[ C_LayerIdx[ 0 ] ].name; //fl.trace("C_LayerNameは " + b +" → "+ C_LayerName); //-----シンボルのあるレイヤーを選択していく //C_TL.setSelectedLayers[ C_LayerIdx ]; //-----頭から最後のフレームの選択状態にして、キーフレーム変換 C_TL.setSelectedFrames( 0 , C_LastFrame1 - 1 ); C_TL.convertToKeyframes(); //-----変換したところをコピーしておく C_TL.copyFrames( 0 , C_LastFrame1 - 1 ); var C_LastFrame2 = C_TL.layers[ C_LayerIdx[ 0 ] ].frames.length; //fl.trace("C_LastFrame2(While前)は " + C_LastFrame2 ); while( C_LastFrame2 < P_LastFrame * 2 ){ //-----毎回ラストのフレームを取得する C_LastFrame2 = C_TL.layers[ C_LayerIdx[ 0 ] ].frames.length; //fl.trace("C_LastFrame2(ペースト前)は " + C_LastFrame2 ); //-----後ろにペーストしてしていく C_TL.pasteFrames( C_LastFrame2 , C_LastFrame1 + C_LastFrame2 ); C_LastFrame2 = C_TL.layers[ C_LayerIdx[ 0 ] ].frames.length; //fl.trace("C_LastFrame2(ペースト後)は " + C_LastFrame2 ); } C_LastFrame2 = C_TL.layers[ C_LayerIdx[ 0 ] ].frames.length ; //fl.trace(C_TL.layers[ C_LayerIdx[ 0 ] ].name + "のwhile後のC_LastFrame2は " + C_LastFrame2 + ": P_LastFrameは " + P_LastFrame); //fl.trace("C_TL.frameCountは "+ C_TL.frameCount ); //-----親のフレーム数と合わせるために親のフレーム数以上の部分は削除する C_TL.removeFrames( P_LastFrame , C_LastFrame2 ); //var C_FrameArray2 = C_TL.layers[ C_LayerIdx ].frames; C_LastFrame2 = C_TL.layers[ C_LayerIdx[ 0 ] ].frames.length ; //fl.trace("Remove後のC_LastFrame2は "+ C_LastFrame2 ); for (c = 0; c < C_LastFrame2; c++) { C_TL.currentFrame = c ; var frame2 = C_TL.layers[ C_LayerIdx[ 0 ] ].frames[ c ]; var curFrameElement2 = C_TL.layers[ C_LayerIdx[ 0 ] ].frames[ c ].elements; //fl.trace( c + " : curFrameElement2は " + curFrameElement2.length); //-----各フレームをまわしていき、空白キーフレームじゃなければ、回転・スケール・スキュー・移動を配列に入れていく if ( !frame2.isEmpty && curFrameElement2.length != 0 ){ var elm2 = C_TL.layers[ C_LayerIdx[ 0 ] ].frames[ c ].elements[ 0 ]; elm2.selected = true; arrC_Alp.push( elm2.colorAlphaPercent ); if ( !isNaN(elm2.rotation) ){ //fl.trace("NaNじゃない") arrC_Rot.push( elm2.rotation ); }else{ //fl.trace("NaNやん") arrC_Rot.push( 0 ); } //fl.trace("子の回転は " + elm2.rotation ) arrC_SclX.push( elm2.scaleX ); arrC_SclY.push( elm2.scaleY ); arrC_SkwX.push( elm2.skewX ); arrC_SkwY.push( elm2.skewY ); //fl.trace("skewX " + arrC_SkwX +" __ skewY " + arrC_SkwY) arrC_PosX.push( elm2.x ); arrC_PosY.push( elm2.y ); arrC_Mat_a.push( elm2.matrix.a ); arrC_Mat_b.push( elm2.matrix.b ); arrC_Mat_c.push( elm2.matrix.c ); arrC_Mat_d.push( elm2.matrix.d ); arrC_Mat_tx.push( elm2.matrix.tx ); arrC_Mat_ty.push( elm2.matrix.ty ); }else{ //親の空のフレームの場所をいれていく C_blankFrames.push( c ); arrC_Alp.push( 0 ); arrC_Rot.push( 0 ); arrC_SclX.push( 1 ); arrC_SclY.push( 1 ); arrC_SkwX.push( 0 ); arrC_SkwY.push( 0 ); arrC_PosX.push( 0 ); arrC_PosY.push( 0 ); arrC_Mat_a.push( 1 ); arrC_Mat_b.push( 0 ); arrC_Mat_c.push( 0 ); arrC_Mat_d.push( 1 ); arrC_Mat_tx.push( 0 ); arrC_Mat_ty.push( 0 ); } } //子供の空フレーム //fl.trace("C_blankFrames = " + C_blankFrames); //-----再度現在のラストフレームを取得 C_LastFrame2 = C_TL.layers[ C_LayerIdx[ 0 ] ].frames.length ; //fl.trace("C_LastFrame2 = " + C_LastFrame2); //var C_LastFrame3 = C_TL.frameCount; C_TL.cutFrames( 0 , C_LastFrame2 ); //-----レイヤーを削除しておく C_TL.deleteLayer(); //------------------------------------------------------------------親の階層に戻る---------------------------------------------------------------------------------------- doc.exitEditMode(); //-----同じ名前の新しいレイヤーを作る P_TL.addNewLayer( C_LayerName , "normal" , false ); //fl.trace("C_LayerName : " + C_LayerName); P_TL.pasteFrames( 0 , C_LastFrame2 ); for (d = 0; d < P_LastFrame; d++){ P_TL.currentFrame = d ; //fl.trace("d → " + d + " : 今のレイヤー名は " + P_TL.layers[ P_TL.currentLayer ].name ); var elm3 = P_TL.layers[ P_TL.currentLayer ].frames[ d ].elements[ 0 ]; var mat = elm3.matrix; //fl.trace("ブランクインデックス " + P_blankFrames.indexOf( d ) ); //-----親の方で空白だったフレームは子どもも空白キーフレームに変換 if ( P_blankFrames.indexOf( d ) != -1 ){ //-----エレメントがあると空白キーフレームに変換が使えない・・・ なのでトゥイーン削除&エレメント削除する //C_TL.convertToBlankKeyframes( c ); P_TL.setFrameProperty('tweenType', 'none' , d); if( P_TL.layers[ P_TL.currentLayer ].frames[ d ].isEmpty == false){ doc.deleteSelection(); } //fl.trace("親がBlank "); }else{ if ( C_blankFrames.indexOf( d ) != -1 ){ P_TL.setFrameProperty('tweenType', 'none' , d); //doc.deleteSelection(); //fl.trace(d + "フレームはこどもが空でした"); }else{ elm3.selected = true; elm3.colorAlphaPercent = ( arrP_Alp[ d ] * arrC_Alp[ d ] ) / 100; /*-----3×3の行列 -----a = 水平方向のスケール、b = 垂直方向のスキュー、 c = 水平方向のスキュー、d = 垂直方向のスケール、tx = X座標、ty = Y座標 | a c tx | | b d ty | | 0 0 1 | */ mat.a = arrP_Mat_a[ d ] * arrC_Mat_a[ d ] + arrP_Mat_c[ d ] * arrC_Mat_b[ d ] + arrP_Mat_tx[ d ] * 0 ; //fl.trace(d + " a= " + mat.a); mat.b = arrP_Mat_b[ d ] * arrC_Mat_a[ d ] + arrP_Mat_d[ d ] * arrC_Mat_b[ d ] + arrP_Mat_ty[ d ] * 0 ; //fl.trace(d + " b= " + mat.b); mat.c = arrP_Mat_a[ d ] * arrC_Mat_c[ d ] + arrP_Mat_c[ d ] * arrC_Mat_d[ d ] + arrP_Mat_tx[ d ] * 0 ; //fl.trace(d + " c= " + mat.c); mat.d = arrP_Mat_b[ d ] * arrC_Mat_c[ d ] + arrP_Mat_d[ d ] * arrC_Mat_d[ d ] + arrP_Mat_ty[ d ] * 0 ; //fl.trace(d + " d= " + mat.d); mat.tx = arrP_Mat_a[ d ] * arrC_Mat_tx[ d ] + arrP_Mat_c[ d ] * arrC_Mat_ty[ d ] + arrP_Mat_tx[ d ] * 1 ; //fl.trace(d + " tx= "+ mat.tx ); mat.ty = arrP_Mat_b[ d ] * arrC_Mat_tx[ d ] + arrP_Mat_d[ d ] * arrC_Mat_ty[ d ] + arrP_Mat_ty[ d ] * 1; //fl.trace(d + " ty= " + mat.ty); elm3.matrix = mat; } } elm3.setTransformationPoint({x:0, y:0}); } //fl.trace("今の選択してるレイヤーは " + P_TL.currentLayer + " : " + P_TL.layers[ P_TL.currentLayer ].name); //P_TL.layers[selectedLayers[h]].name P_TL.setSelectedLayers( P_LayerIdx[ 0 ] ); //fl.trace("そして今のレイヤーは " + P_TL.currentLayer + " : " + P_TL.layers[ P_TL.currentLayer ].name); P_TL.currentFrame = P_minKeyFrame; //fl.trace( " P_LayerIdx[ 0 ]は " + P_LayerIdx[ 0 ] + " : P_minKeyFrameは" + P_minKeyFrame ); doc.selectNone(); P_TL.layers[ P_LayerIdx[ 0 ] ].frames[ P_minKeyFrame ].elements[ 0 ].selected = true; //fl.trace("せれくしょん " + doc.selection.length); //------------------------------------------------------------------また子の階層に入る---------------------------------------------------------------------------------------- doc.enterEditMode('inPlace'); //-----配列を初期化する arrC_Alp = []; arrC_Rot = []; arrC_SclX = []; arrC_SclY = []; arrC_SkwX = []; arrC_SkwY = []; arrC_PosX = []; arrC_PosY = []; arrC_Mat_a = []; arrC_Mat_b = []; arrC_Mat_c = []; arrC_Mat_d = []; arrC_Mat_tx = []; arrC_Mat_ty = []; C_blankFrames = []; } //------------------------------------------------------------------最後に親の階層に戻る---------------------------------------------------------------------------------------- doc.exitEditMode(); //-----配列を初期化する arrP_Alp = []; arrP_Rot = []; arrP_SclX = []; arrP_SclY = []; arrP_SkwX = []; arrP_SkwY = []; arrP_PosX = []; arrP_PosY = []; arrP_Mat_a = []; arrP_Mat_b = []; arrP_Mat_c = []; arrP_Mat_d = []; arrP_Mat_tx = []; arrP_Mat_ty = []; P_blankFrames = []; P_TL.setSelectedLayers( P_LayerIdx[ 0 ] ,true); //fl.trace("処理後:親のレイヤーネームは " + P_TL.layers[ P_LayerIdx[ 0 ] ].name ); var P_frame = P_TL.layers[ P_LayerIdx[ 0 ] ].frames; var elmCheck = false; var P_frmLen = P_frame.length; for (e=0; e < P_frmLen ; e++){ if( P_frame[e].isEmpty == false){ //-----親のレイヤーのフレームをチェックしていき、もしエレメントがあったらelmCheckをtrueにする if( P_frame[e].elements[0].height != 0 && P_frame[e].elements[0].width != 0){ elmCheck = true; break; } } } //fl.trace("elmCheck = " + elmCheck); //-----上記でレイヤー内のエレメントの有無を確認したので、もしエレメントがなかったらその親レイヤーを削除 if (elmCheck == false){ fl.trace( P_TL.layers[ P_LayerIdx[ 0 ] ].name + " を削除しました"); P_TL.deleteLayer(P_LayerIdx[ 0 ] ); } } //fl.trace("完了しました"); alert("完了しました"); } function fileCopy (){ var filePath1 = doc.pathURI; //fl.trace ("filePath1は " + filePath1 ); //-----後ろの.flaを取り除く var filePath2 = filePath1.substr ( 0 , ( filePath1.length - 4 ) ); //fl.trace ("filePath2は " + filePath2 ); if (filePath1.indexOf("_copy") != -1 ){ fl.saveDocument("", filePath1 ); fl.trace("コピーを上書きしました"); }else{ fl.saveDocument("", filePath2 + "_copy.fla"); fl.trace("コピーとして保存しました"); } }
コメントをお書きください