ActionScript 3.0入門ノート CS4でタグ「graphics」が付けられているもの

(section09-03 Flash Player10の新しいGraphicsメソッドから抜粋)

 drawTriangles()を使うと簡単に三角形を描くことができます。drawTriangles()では、三角形の頂点をベクターで指定します。次のサンプルではローカル座標(0,0)、(150,80)、(-50,120)を頂点とした三角形を描いています。drawTriangles()の引数のベクターverticesではこの3つの座標を連続した6個の数値で指定します(4〜6行目)。

[:script:]drawTriangles()を使って三角形を描く
var shape:Shape=new Shape();
shape.graphics.beginFill(0xFF0000);
//頂点の座標
var vertices:Vector.<Number>=Vector.<Number>([0,0, 150,80, -50,120]);
//三角形を描く
shape.graphics.drawTriangles(vertices);
shape.graphics.endFill();
shape.x=200;
shape.y=100;
addChild(shape);
fig09-03-08_shiji.jpg
(section09-03 Flash Player 10の新しいGraphicsメソッドから抜粋)

 次にdrawPath()を使って図形を描くサンプルを示します。これを実行すると19行目でシェイプが作られ、このシェイプに図形を描画されます。drawPath()での描画はdrawRect()などの描画の手順と同じように図形を塗るならば描画する前にbeginFill()で塗りを開始し、描画終了でendFill()を実行します(20〜22行目)。実際に描画を行っているのは21行目のdrawPath()です。drawPathの3個の引数のcommandsとdataとwindingには、描画で必要となる値を入れておきます。
 commandsとdataはベクターです。ベクターを作るには、new Vector.<ベース型>()のようにベース型(値のデータ型)を指定してインスタンスを作ります。commandsは要素の値がint型なのでを指定します(4行目)。
fig09-03-01.jpg
[:script:]drawPath()を使って図形を描く
var w:int=150;
var h:int=120;
//描画コマンド
var commands:Vector.<int>=new Vector.<int>();
commands.push(GraphicsPathCommand.MOVE_TO);
commands.push(GraphicsPathCommand.LINE_TO);
commands.push(GraphicsPathCommand.CURVE_TO);
commands.push(GraphicsPathCommand.LINE_TO);
//描画に使う座標
var data:Vector.<Number>=new Vector.<Number>();
data.push(0,0);
data.push(w,0);
data.push(w,h);
data.push(0,h);
data.push(0,0);
//描画の交差領域の塗りの処理法
var winding:String=GraphicsPathWinding.EVEN_ODD;
//図形を描く
var shape:Shape=new Shape();
shape.graphics.beginFill(0xFF0000);
shape.graphics.drawPath(commands, data, winding);
shape.graphics.endFill();
shape.x=200;
shape.y=150;
addChild(shape);
 dataベクターを見るとわかるようにこの図形の描画には5個の点を使用し、ベクターには合計10個の値が入ります。commandsでは、dataから値を順に取り出してメソッドを実行していきます。commandsに追加したメソッドとdataの座標とを付き合わせると次のようになっています。moveTo()とlineTo()の引数は2個ですが、curveTo()はコントロールポイントの座標があるので4個の値を必要とします。
data.push(0,0);//moveTo(0,0)
data.push(w,0);//lineTo(w,0)
data.push(w,h);//curveTo(w,h,0,h)
data.push(0,h);
data.push(0,0);//lineTo(0,0)
(section09-02 図形の塗りと線の塗りから抜粋)

 図形や線をビットマップデータで塗ることができます。図形をビットマップデータで塗るにはbeginBitmapFill()、線をビットマップデータで塗るにはlineBitmapStyle()でそれぞれ塗りに使うビットマップデータや塗り方を指定します。

書式:図形をビットマップで塗る
beginBitmapFill(bitmap:BitmapData, matrix:Matrix = null, repeat:Boolean = true, smooth:Boolean = false):void

書式:線をビットマップで塗る
lineBitmapStyle(bitmap:BitmapData, matrix:Matrix = null, repeat:Boolean = true, smooth:Boolean = false):void

 bitmapdataはビットマップデータです。ビットマップデータはBitmapDataクラスで作りますが、ビットマップシンボルや外部イメージファイルから読み込んで作るといったこともできます。matrixはグラデーションの塗りでも使用した変形マトリックスです。ビットマップの拡大縮小や回転などを設定できます。
 repeatはビットマップのサイズより大きな領域を塗ったときにビットマップのパターンを繰り返すかどうかをtrue、falseで指定します。falseを指定した場合はパターンの繰り返しを行わずにビットマップの境界の色がそのまま連続します。smoothは伸縮したビットマップにスムージング処理のアルゴリズムを適用するかどうかを指定します。trueに設定するとスムーズになりますが、表示の処理はfaleのほうが高速です。


図形をビットマップで塗る
 次のサンプルはスクリプトで描いた四角形をビットマップシンボルのビットマップデータで塗っています。ビットシンボルからビットマップデータを取り出すには、ビットマップシンボルのリンケージ書き出し設定を行い、new演算子でインスタンス化します(4行目)。このとき、EZ_logo(0,0)のように2個の数値の引数が必要です。数値の大きさには意味がありません。
 ビットマップデータが作れたならば、図形を描く前にbeginBitmapFill()を実行し、図形を描いたらendFill()を実行します。beginBitmapFill()の第2引数の変換マトリックスは45度回転させています。第4引数のsmoothもtrueにしているので、パターンを回転させていてもイメージのジャギーが目立たずにスムーズです(9行目)。

fig09-02-07.jpg  fig09-02-08.jpg

[:script:]ビットマップデータのパターンで塗った円形を描く
var shape1:Shape=new Shape();
var r:int=150;
//ビットマップデータを作る
var bmpdata:BitmapData=new EZ_logo(0,0);
//変換マトリックス
var mtrx:Matrix=new Matrix();
mtrx.rotate(Math.PI/4);
//図形をビットマップデータのパターンで塗る
shape1.graphics.beginBitmapFill(bmpdata,mtrx,true,true);
//円を描く
shape1.graphics.drawCircle(0,0,r);
//塗り終わり
shape1.graphics.endFill();
//ステージの中央に置く
shape1.x=stage.stageWidth/2;
shape1.y=stage.stageHeight/2;
addChild(shape1);
(section09-02 図形の塗りと線の塗りから抜粋)

 線をグラデーションで塗りたい場合は、先にlineStyle()で線の太さや両端の形などを指定し、続いてlineGradientStyle()を実行してグラデーションを指定します。線の設定を行ったならば線や図形を描きます。
 次の例は黄色と黒の斜めのグラデーションで線を縞々に塗っています。縞々の繰り返しのグラデーションにするには、spreadオプションをSpreadMethod.REFLECTかSpreadMethod.REPEATのどちらかにします。SpreadMethod.REPEATは単純な繰り返しですが、SpreadMethod.REFLECTは色の変化が反転するように繰り返されます(14行目)。縞の幅はcreateGradientBox()の第1引数で10に設定しています(12行目)。

fig09-02-05.jpg

[:script:]]四角形の線を斜めの縞々で塗る
var shape1:Shape=new Shape();
var w:int=250;
var h:int=200;
//線幅
shape1.graphics.lineStyle(15);
//線のグラデーション
var type:String=GradientType.LINEAR;
var colors:Array=[0xFFFF00,0x000000];
var alphas:Array=[1, 1];
var ratios:Array=[0,255];
var mtrx:Matrix=new Matrix();
mtrx.createGradientBox(10,h,0,0,0)
mtrx.rotate(Math.PI/4);
var spread:String=SpreadMethod.REFLECT;
shape1.graphics.lineGradientStyle(type,colors,alphas,ratios,mtrx,spread);
//四角形を描く
shape1.graphics.beginFill(0xFFFF99);
shape1.graphics.drawRect(0,0,w,h);
shape1.graphics.endFill();
//ステージの中央に置く
shape1.x=stage.stageWidth/2-w/2;
shape1.y=stage.stageHeight/2-h/2;
addChild(shape1);

マスクの利用

|
(section09-01 基本的な図形を描くから抜粋)

 シェイプやスプライトで描く図形の活用としてマスクをあげることができます。次の例では写真のムービークリップインスタンスに円を描いたシェイプをマスクとして設定し、写真を円形に切り抜いて表示しています。

fig09-01-17.jpg  fig09-01-18.jpg

[:script:]写真にシェイプマスクをかける
//コンテナを作る
var container:Sprite=new Sprite();
container.x=100;
container.y=50;
addChild(container);
//写真のmcを作る
var photo_mc:MovieClip=new Photo();
//マスクに使うシェイプを作る
var shape1:Shape=new Shape();
shape1.graphics.beginFill(0xFF0000);
shape1.graphics.drawCircle(0,0,100);
shape1.graphics.endFill();
shape1.x=photo_mc.width/2;
shape1.y=photo_mc.height/2;
//コンテナに追加する
container.addChild(photo_mc);
container.addChild(shape1);
//shape1をphoto_mcのマスクに設定する
photo_mc.mask=shape1;

(section09-01 基本的な図形を描くから抜粋)

 描いた図形や線を消すにはclear()を実行します。描画によるアニメーションを行うには、描画とclear()を繰り返します。
 次のサンプルは曲線の描き方で使ったcurveTo.flaを改良し、線を結ぶインスタンスをドラッグできるようにしたものです。インスタンスをドラッグすると、それに合わせて線が再描画されます(36〜45行目)。

fig09-01-16b.jpgswfを試す

[:script:]ドラッグできるインスタンスを直線と曲線で結ぶ
var shape1:Shape=new Shape();
var stageRect:Rectangle=new Rectangle(0,0,stage.stageWidth,stage.stageHeight);
//ステージに配置する
shape1.x=0;
shape1.y=0;
addChild(shape1);

//最初に線を引く
updateLines();

//頂点をドラッグできるようにする
pt1.addEventListener(MouseEvent.MOUSE_DOWN, onStartDrag);
pt2.addEventListener(MouseEvent.MOUSE_DOWN, onStartDrag);
ctrlPt.addEventListener(MouseEvent.MOUSE_DOWN, onStartDrag);
stage.addEventListener(MouseEvent.MOUSE_UP, onStopDrag);

//ドラッグ開始
function onStartDrag(eventObj:MouseEvent):void {
	var mc:MovieClip=eventObj.target as MovieClip;
	mc.startDrag(false,stageRect);
	stage.addEventListener(MouseEvent.MOUSE_MOVE,updateLines);
}

//ドラッグ終了
function onStopDrag(eventObj:MouseEvent):void {
	stopDrag();
	stage.removeEventListener(MouseEvent.MOUSE_MOVE,updateLines);
}

//ドラッグ中は再描画する
function updateLines(eventObj:MouseEvent=null):void {
	if (eventObj != null) {
		//ドラッグに合わせて画面更新
		eventObj.updateAfterEvent();
	}
	//描画を消す
	shape1.graphics.clear();
	//pt1-pt2の曲線を引く
	shape1.graphics.lineStyle(1,0x000000);
	shape1.graphics.moveTo(pt1.x,pt1.y);
	shape1.graphics.curveTo(ctrlPt.x,ctrlPt.y,pt2.x,pt2.y);
	//pt1-ctrlPtの接線を引く
	shape1.graphics.lineStyle(1,0x666666);
	shape1.graphics.moveTo(pt1.x,pt1.y);
	shape1.graphics.lineTo(ctrlPt.x,ctrlPt.y);
}

塗りの閉じ

|
(section09-01 基本的な図形を描くから抜粋)

 endFill()を実行しなくても図形の塗りは実行されます。たとえば、次のように円を描いた場合、endFill()を実行しなくても図形が塗られます。

[:script:]endFill()を実行していない
var sp:Sprite=new Sprite();
sp.graphics.beginFill(0xFF0000);
sp.graphics.drawCircle(0,0,100);
sp.x=200;
sp.y=150;
addChild(sp);

fig09-01-13.jpg
 では、endFill()は必要ないかと言えばそうではありません。次のように重なるように円を描いた場合、塗りが重なっている部分は塗られません。

[:script:]円を重ねて描くと、塗りが重なった部分が塗られません。
var sp:Sprite=new Sprite();
sp.graphics.beginFill(0xFF0000);
sp.graphics.drawCircle(0,0,100);
sp.graphics.drawCircle(-80,0,50);
sp.x=200;
sp.y=150;
addChild(sp);

fig09-01-14.jpg
 2つの円がどちらも塗られるようにするには、図形の塗りの終了ごとにendFill()を実行することで円を1個ずつ塗ります。

[:script:]重なっている円を塗る
var sp:Sprite=new Sprite();
//塗りの開始
sp.graphics.beginFill(0xFF0000);
sp.graphics.drawCircle(0,0,100);
sp.graphics.endFill();
//塗り終了
//塗りの開始
sp.graphics.beginFill(0xFF0000);
sp.graphics.drawCircle(-80,0,50);
sp.graphics.endFill();
//塗り終了
sp.x=200;
sp.y=150;
addChild(sp);

fig09-01-15.jpg

図形の塗り

|
(section09-01 基本的な図形を描くから抜粋)

 図形の内部を塗るには図形の描画を開始する前にbeginFill()を実行し、図形の描画が終わったならばendFill()で塗りを終了します。beginFill()では塗り色と塗りの透明度を指定できます。
 次のサンプルではpt1からpt2、pt2からpt3の直線を2本引いています。2本の線では図形として閉じていませんが、塗りを行うと自動的にpt3からpt1への線が引かれて3点を頂点とした三角形になり、内部が塗られます。

fig09-01-11a.jpg fig09-01-11b.jpg
[:script:]図形を塗りつぶす
var pt1:Point=new Point(0,0);
var pt2:Point=new Point(150,100);
var pt3:Point=new Point(80,150);
var sp:Sprite=new Sprite();
//線のスタイル
sp.graphics.lineStyle(3,0x000000);
//塗り始め
sp.graphics.beginFill(0x999999);
//線を引く
sp.graphics.moveTo(pt1.x,pt1.y);
sp.graphics.lineTo(pt2.x,pt2.y);
sp.graphics.lineTo(pt3.x,pt3.y);
//塗り終わり
sp.graphics.endFill();
sp.x=100;
sp.y=100;
addChild(sp);

 また、線のスタイルを指定している6行目を取り去ると線が引かれれなくなりますが、線は見えなくても図形の塗りが行われます。
fig09-01-12.jpg

曲線を引く

|
(section09-01 基本的な図形を描くから抜粋)

 曲線はcurveTo()を使って引きます。描き方の手順はlineTo()を使った直線の描き方と基本的に同じですが、curveTo()では曲線の終点とは別に曲線の接線方向を示すコントロールポイントを指定します。
 次の例ではステージにpt1、pt2、ctrlPtの3つのインスタンスが作ってあります。そして、ctrlPtをコントロールポイントの座標に使い、始点pt1と終点pt2を結ぶ曲線を引きます(2〜5行目)。
 さらに始点pt1とコントロールポイントctrlPの直線も描いています。始点pt1とコントロールポイントctrlPの直線を引くと、この直線を接線として曲線が描かれているのがわかります(7〜9行目)。
 なお、lineTo()、curveTo()で指定する座標はshape1のローカル座標ですが、pt1、pt2、ctrlPtの座標はステージを基準としたグローバル座標です。この座標を合わせるためにshape1はステージの(0,0)の位置にaddChild()します。

fig09-01-10.jpgswfを試す

[:script:]曲線を引く
var shape1:Shape=new Shape();
//pt1-pt2の曲線を引く
shape1.graphics.lineStyle(1,0x000000);
shape1.graphics.moveTo(pt1.x,pt1.y);
shape1.graphics.curveTo(ctrlPt.x,ctrlPt.y,pt2.x,pt2.y);
//pt1-ctrlPtの接線を引く
shape1.graphics.lineStyle(1,0x666666);
shape1.graphics.moveTo(pt1.x,pt1.y);
shape1.graphics.lineTo(ctrlPt.x,ctrlPt.y);
//ステージに配置する
shape1.x=0;
shape1.y=0;
addChild(shape1);
(section09-01 基本的な図形を描くから抜粋)

 次の例はJapanと書いたjapan_mcインスタンスにトゲを刺すように線を引いています。まず、japan_mcの矩形内のランダムな点pt1(pt1x,pt1y)を求めます(9、10行目)。その座標をグローバル座標の点pt1に変換し、pt1がjapan_mcのイメージと衝突しているかどうかをhitTestPoint()で判定します(15行目)。そして、衝突しているならばその点を線を引く始点pt1にし、線の終点pt2は、ランダムに決めた線の長さと角度からPoint.polar(lineLength,rad)で計算します(19〜24行目)。そのままではpt2は(0,0)からの点になるので、pt1の位置からの距離と角度になるようにoffset()で座標を補正します(25行目)。これで線の始点pt1と終点pt2が決まったので、pt1にペン先を移動してpt2までの線を引きます(27、28行目)。

fig09-01-07.jpgswfを試す

[:script:]インスタンスにトゲを刺すように線を引く
//線(トゲ)の本数
var num:int=4000;
//線を描くシェイプ
var lines_shape:Shape=new Shape();
addChild(lines_shape);
//線を繰り返し描く
for (var i=1; i<=num; i++) {
	//線の始点pt1の座標
	var pt1x:Number=japan_mc.width*Math.random();
	var pt1y:Number=japan_mc.height*Math.random();
	var pt1:Point=new Point(pt1x,pt1y);
	//pt1をグローバル座標に変換する
	pt1=japan_mc.localToGlobal(pt1);
	//始点pt1がjapan_mcに刺さっているならば線を描く
	if (japan_mc.hitTestPoint(pt1.x,pt1.y,true)) {
		//線のスタイル
		var lineColor:Number=0xFFFFFF*Math.random();
		lines_shape.graphics.lineStyle(1,lineColor,0.6);
		//線の長さ
		var lineLength:Number=3+17*Math.random();
		//線の角度
		var rad:Number=2*Math.PI*Math.random();
		//線の終点pt2を求める
		var pt2:Point=Point.polar(lineLength,rad);
		pt2.offset(pt1.x,pt1.y);
		//線を引く
		lines_shape.graphics.moveTo(pt1.x,pt1.y);
		lines_shape.graphics.lineTo(pt2.x,pt2.y);
	}
}

 *元々はここまでのサンプルだったんですが、せっかくなのでトゲが動くバージョンも作りました。(書籍には動くスクリプトも掲載してあります)
トゲが動くバージョン

直線を引く

|
(section09-01 基本的な図形を描くから抜粋)

 直線を描くにはmoveTo()とlineTo()を使います。moveTo()は線を引き始める座標にペン先を移動します。lineTo()は現在のペン先位置から指定の座標まで直線を引きます。次の例では円を描いた後に円の中心を水平に横切る直線を引いています。横線を引く前にlineStyle()を設定し直しているので、横線は円の線とは違うスタイルで引かれます。
fig09-01-06.jpgswfを試す


[:script:]円に横線を引く
var shape1:Shape=new Shape();
shape1.graphics.lineStyle(5,0x666666);
//円を描く
var r:int=40;
shape1.graphics.drawCircle(0,0,r);
//横線を引く
shape1.graphics.lineStyle(10,0xFF0000,1,false,"normal","round");
var len:int=2*(r+10);
shape1.graphics.moveTo(len/2,0);
shape1.graphics.lineTo(-len/2,0);
//ステージの中央に置く
shape1.x=stage.stageWidth/2;
shape1.y=stage.stageHeight/2;
addChild(shape1);
(section09-01 基本的な図形を描くから抜粋)

 図形を描く線の色とスタイルはlineStyle()の引数で設定します。引数は次の書式のように8つあります。

書式:
lineStyle(thickness:Number = NaN, color:uint = 0, alpha:Number = 1.0, pixelHinting:Boolean = false, scaleMode:String = "normal", caps:String = null, joints:String = null, miterLimit:Number = 3):void

 pixelHintingは角丸四角形の角などの直線と曲線のつながりの部分でのピクセルのずれがめだたないように修正するかどうかを指定する設定です。初期値は修正しないfalseになっていますが、修正する場合はtrueに設定します。線の設定を変えて角丸四角形を描いた場合の比較例を次に示します。左がpixelHintingがfalseのshape1、右がpixelHintingがtrueのshape2です。左のshape1は左辺の角と辺のつながりが不連続になっている部分が目立ちます。

fig09-01-05.jpgswfを試す

[:script:]lineStyleのpixelHintingの設定を変えて角丸四角形を描く
var shape1:Shape=new Shape();
var shape2:Shape=new Shape();
//pixelHinting=false
shape1.graphics.lineStyle(3,0x000000,1,false);
shape1.graphics.drawRoundRect(0,0,100,100,30,80)
shape1.x=100;
shape1.y=150;
addChild(shape1);
//pixelHinting=true
shape2.graphics.lineStyle(3,0x000000,1,true);
shape2.graphics.drawRoundRect(0,0,100,100,30,80)
shape2.x=250;
shape2.y=150;
addChild(shape2);
(section09-01 基本的な図形を描くから抜粋)

 図形の描画はGraphicsクラスの描画メソッドを使いますが、Graphicsクラスのインスタンスを作って直接利用することはできません。また、Graphicsクラスを継承して描画可能なクラスを再定義することもできません。
 Graphicsクラスの描画メソッドを利用するには、Shapeクラス、Spriteクラス、そしてSpriteクラスのサブクラスであるMovieClipクラスのgraphicsプロパティを介してGraphicsクラスのオブジェクトにアクセスします。

図形を描く
 Graphicsクラスの描画メソッドを使うと、円、楕円、四角形、角丸四角形の図形を描くことができます。次のスクリプトはGraphicsクラスのdrawCircle()を使って、Shapeクラスのインスタンスに円を描いています。
 なお、Shapeクラスは単純なシェイプを作成するときに利用されます。ShapeクラスはSpriteクラスと違ってDisplayObjectContainerとInteractiveObjectを継承していません。つまり、ほかの表示オブジェクトを入れ子にもつことができず、クリックイベントなどのイベントを受け取りません。その分だけSpriteクラスよりもメモリを消費しません。

[:script:]円を描く
var shape1:Shape=new Shape();
//線幅3、赤色の線
shape1.graphics.lineStyle(3,0xFF0000);
//円を描く
shape1.graphics.drawCircle(0,0,80);
//ステージの中央に置く
shape1.x=stage.stageWidth/2;
shape1.y=stage.stageHeight/2;
addChild(shape1);
 drawCircle(0,0,80)は、中心点の座標(0,0)と半径80の円を描きます。座標の(0,0)はステージの座標ではなく、addChild()する親オブジェクトの中心点を基準とするローカル座標です。図形を描く線はlineStyle()で指定します。lineStyle()のオプションはたくさんありますが、ここでは線幅3と線色0xFF0000(赤)を指定しています。

fig09-01-01.jpgswfを試す

まったく新しいAS3の世界!
694a.jpg
Adobe Flash CS4
詳細!ActionScript3.0入門ノート[完全改訂版](CD-ROM付)

楽しいActionScript。
新たなる1歩へと踏み出しましょう。
■内容は?→ 目次を見る
■評判は?→ 書評を読む
この本を書いたわけ

タグ

最近のコンテンツはインデックスページで見られます。過去に書かれたものはアーカイブのページで見られます。

あわせて読みたいブログパーツ