サイトトップ

Director Flash 書籍 業務内容 プロフィール

Adobe Flash非公式テクニカルノート

指定座標を中心にMovieClipを回転させる

ID: FN0708001 Product: Flash Platform: All Version: MX 2004 and above/ActionScript 2.0 and 3.0

ActionScriptでタイムライン上のインスタンスを回転すると、基準点が中心になります。したがって、オーサリング(ムービー作成)時に、回転の中心にしたい座標を基準点に合わせておく必要があります。しかし、たとえば外部ファイルをインスタンスにロードする場合には、基準点は読込んだイメージの左上隅になり、座標を選ぶことができません。

この場合のひとつの対応方法は、ロードのターゲットとなるインスタンスを、さらに別のMovieClipシンボルに入れ子にしておくことです。そして、ターゲットインスタンスを移動して、その回転の中心座標を親の基準点に合わせます。そのうえで、ターゲットでなく、親のインスタンスを回転するという手法です。

しかし本稿では、直接インスタンスを回転し、中心座標はスクリプトで補正するという方法をご紹介します。


1. ActionScript 2.0の場合 − MovieClip.localToGlobal()メソッドを使う
考え方としては、まず第1に、インスタンスの回転の中心座標を記録します。そして第2に、取りあえず基準点を中心にして、必要な角度を回転します。すると、本当は動いてほしくない中心座標がずれてしまいます。そこで第3に、その中心座標のずれを計算し、元の位置に戻すのです。

その場合、回転するターゲットインスタンス自身は、ずれを計測することができません。インスタンスが配置された親や、さらに上位のタイムラインなど、動かない座標空間上で位置を記録する必要があります[*1]。そのときに使えるメソッドが、MovieClip.localToGlobal()です。

MovieClip.localToGlobal()メソッドは、MovieClipインスタンスから見た(ローカル)座標を、ステージの原点であるムービーの左上隅から見た(グローバル)座標に変換してくれます[*2]。ただし、その使い方は、少々独特です。

// [1]xy座標値がx、yプロパティとして設定されたObjectインスタンスを作成
var 座標をもったオブジェクト:Object = {x:x座標値, y:y座標値};
// [2]MovieClipをターゲットに、Objectインスタンスを引数としてメソッドを呼出す
MovieClipインスタンス.localToGlobal(座標をもったオブジェクト);
// [3]Objectインスタンスのx、yプロパティ値が直接変換される
trace([座標をもったオブジェクト.x, 座標をもったオブジェクト.y]);

[1]まず、Objectインスタンスを作成し、そのx、yというプロパティに、グローバル座標に変換したいMovieClipインスタンス上のローカルのxy座標を設定します。

[2]つぎに、MovieClipインスタンスをターゲットに、MovieClip.localToGlobal()メソッドを呼出します。その際、[1]で作成したObjectインスタンスを、メソッドに引数として渡します。

[3]すると、MovieClip.localToGlobal()メソッドは、引数のObjectインスタンスのx、yプロパティ値を直接変換します。つまり、Objectインスタンスのx、yプロパティの値を調べると、それぞれグローバル座標に変換されているという訳です。

初めに述べた考え方にもとづき、MovieClip.localToGlobal()メソッドを使って、MovieClipインスタンスを、指定した中心座標で指定角度回転する関数が、以下のスクリプト001です。

スクリプト001■MovieClipインスタンスを指定した中心座標で指定角度回転する関数 − ActionScript 2.0

// フレームアクション
// xRotateAt(): 指定座標を中心にMovieClipインスタンスを回転する関数
// 戻り値: なし
// 引数: ターゲットインスタンス, x座標値, y座標値, 回転角
function xRotateAt(target_mc:MovieClip, nX:Number, nY:Number, nDegree:Number):Void {
// 回転前と回転後の座標値を記録するObjectインスタンス作成
  var oStartPoint:Object = {x:nX, y:nY};
  var oEndPoint:Object = {x:nX, y:nY};
// 回転前と回転後のグローバル座標にそれぞれ変換
  target_mc.localToGlobal(oStartPoint);
  target_mc._rotation = nDegree;
  target_mc.localToGlobal(oEndPoint);
// 回転前と回転後の座標の差を補正
  target_mc._x += oStartPoint.x-oEndPoint.x;
  target_mc._y += oStartPoint.y-oEndPoint.y;
}

指定した中心座標をx、yプロパティとしてもつObjectインスタンスは、ふたつ作成しています。ひとつ(oStartPoint)は、回転前のグローバル座標として保持します。そして、もうひとつ(oEndPoint)は、回転後のグローバル座標として取得します。ふたつのObjectインスタンスのx、yプロパティの値の差が、回転によりずれた座標値になります。したがって、その差をMovieClipインスタンスの座標値に加えて、もとの座標に戻しているのです。

上記スクリプト001を記述したタイムラインに、テストとしてMovieClipインスタンスmy_mcを配置しましょう。基準点は、中央以外のどこでも構いません。そして、上記フレームアクションに以下のステートメントを追加します。[ムービープレビュー]を実行して、MovieClipインスタンスmy_mcをクリックすると、インスタンスの真ん中を中心として、15度ずつ回転します。

// スクリプト001に追加
// MovieClipインスタンスmy_mcを配置
var nX:Number = my_mc._width/2;
var nY:Number = my_mc._height/2;
my_mc.onRelease = function():Void {
  xRotateAt(this,nX,nY,this._rotation+15);
};

[*1]「座標空間」については、Flash ActionScript Helper「座標空間」をご参照ください。

[*2] 逆に、グローパル座標をローカル座標に変換するMovieClip.globalToLocal()というメソッドもあります。使い方は、MovieClip.localToGlobal()メソッドと同様です。


2. ActionScript 3.0の場合 − MatrixTransformer.rotateAroundInternalPoint()メソッドを使う
ActionScript 3.0には、MatrixTransformer.rotateAroundInternalPoint()という、指定座標を中心に回転の変形を加えるための静的メソッドが実装されています。ただし、このメソッドは、インスタンスを直接変形するのでなく、MatrixTransformerというクラス名のとおり、インスタンスのもつDisplayObject.transformプロパティのmatrixという変換行列を操作することにより、インスタンスに変形を加えます。

Matrixオブジェクトは、インスタンスの移動や拡大・縮小、回転、傾斜などの変形の情報をもっており、変換行列というかたちで数学的に表現されます。この変換行列を取出し、その情報を操作すると、インスタンスに変形を加えることができます。MatrixTransformer.rotateAroundInternalPoint()メソッドは、Matrixオブジェクトに対して、指定座標を中心とした回転の操作を行うものです。シンタックスは、つぎのとおりです[*3]

MatrixTransformer.rotateAroundInternalPoint(Matrixインスタンス, x座標値, y座標値, 回転角の度数値)

このメソッドを使って、インスタンスを、指定した中心座標で指定角度回転する関数が、以下のスクリプト002です。

スクリプト002■インスタンスを指定した中心座標で指定角度回転する関数 − ActionScript 3.0

// フレームアクション
// クラスのimport(省略可)
import flash.display.DisplayObject;
import flash.geom.Matrix;
import fl.motion.MatrixTransformer;
// xRotateAt(): 指定座標を中心にMovieClipインスタンスを回転する関数
// 戻り値: なし
// 引数: ターゲットインスタンス, x座標値, y座標値, 回転角
function xRotateAt(target:DisplayObject, nX:Number, nY:Number, nDegree:Number):void {
  var myMatrix:Matrix = target.transform.matrix;
  MatrixTransformer.rotateAroundInternalPoint(myMatrix, nX, nY, nDegree);
  target.transform.matrix = myMatrix;
}

関数xRotateAt()の本体内の処理は、極めてシンプルです。注意すべき点は、MatrixTransformer.rotateAroundInternalPoint()メソッドで操作したMatrixインスタンスは、改めてインスタンスのDisplayObject.transform.matrixプロパティに設定しないと、変形が有効にならないということです。

上記スクリプト002をテストするには、スクリプトの記述されたタイムラインにMovieClipインスタンスmy_mcを配置して、上記フレームアクションに以下のステートメントを追加します。[ムービープレビュー]を実行して、MovieClipインスタンスmy_mcをクリックすると、基準点の位置にかかわらず、真ん中を中心として15度ずつ回転します。

// スクリプト002に追加
// MovieClipインスタンスmy_mcを配置
import flash.events.MouseEvent;   // 省略可
var nX:Number = my_mc.width/2;
var nY:Number = my_mc.height/2;
my_mc.addEventListener(MouseEvent.CLICK, click);
function click(eventObject:MouseEvent):void {
  xRotateAt(my_mc, nX, nY, 15);
}

[*3] インスタンスの配置された親(DisplayObjectContainer)インスタンスの座標を中心に、Matrixオブジェクトに回転の操作をするMatrixTransformer.rotateAroundExternalPoint()というメソッドもあります。


作成者: 野中文雄
作成日: 2007年8月31日


Copyright © 2001-2007 Fumio Nonaka.  All rights reserved.