[AS3] 動態複製顯示物件



如何不用連結(Linkage)的方式用AS3動態複製顯示物件。

執行結果:

有時候我們在元件庫中沒有或不想定義外部連結Class,或者要複製本來就是動態產生的物件,這時候可能就只好用動態複製的方式了。由於AS3沒有AS2的attachMovieClip以及duplicateMovieClip的方法,因此動態複製的功能就要自己來做了。

網路上有利用ByteArray來做memory copy,類似Array的深複製方法,不過這方法我沒成功。也有使用Loader再做一次載入的方法,要加一個Loader和監聽Complete事件,感覺上比較麻煩點。試過之後覺得以下兩種複製的方法比較好:其中一種是利用getQualifiedClassName取得該物件的Class名稱後,再利用getDefinitionByName將名稱轉為Class定義,也就是建構式。另一種寫法則是利用Object的constructor直接取得該物件的建構式。

先測試一下一個匿名,也就是動態產生的MovieClip經過getQualifiedClassNamegetQualifiedSuperclassNamegetDefinitionByName後的結果:

/**
 * Duplicate Display Object Example.
 * @Author:  Scissor
 */
var tmpClip:MovieClip=newMovieClip();
 
trace(tmpClip);					// [object MovieClip]
trace(getQualifiedClassName(tmpClip));		// flash.display::MovieClip
trace(getQualifiedSuperclassName(tmpClip));	// flash.display::Sprite
 
trace(getDefinitionByName(getQualifiedClassName(tmpClip)));	// [class MovieClip]
trace(Object(tmpClip).constructor);				// [class MovieClip]

實際使用時請注意,如果是在Flash IDE中的物件,一定要加上程式碼,若沒有的話可以在第一影格加上stop()或者play()即可。否則的話debug的時候雖然感覺上是複製成功,物件屬性都有複製到,可是在場景上卻完全找不到的現象(應該是Flash的Bug!如果您知道如何解決煩請留言跟大家說,感謝!):

import flash.events.MouseEvent;
import flash.display.MovieClip;

btnCopy1.addEventListener(MouseEvent.CLICK, onBtnCopy1Click);
btnCopy2.addEventListener(MouseEvent.CLICK, onBtnCopy2Click);
btnClear.addEventListener(MouseEvent.CLICK, onBtnClearClick);

function onBtnCopy1Click(e:MouseEvent):void {
	var tmpClip:MovieClip = CopyDisplayObj(mcLogo) as MovieClip;
	tmpClip.x = Math.random() * stage.stageWidth;
	tmpClip.y = Math.random() * stage.stageHeight;
	tmpClip.name = "tmpClip";
	addChildAt(tmpClip, 0);
}

function onBtnCopy2Click(e:MouseEvent):void {
	var tmpClip:MovieClip = DuplicateDisplayObj(mcLogo) as MovieClip;
	tmpClip.x = Math.random() * stage.stageWidth;
	tmpClip.y = Math.random() * stage.stageHeight;
	tmpClip.name = "tmpClip";
	addChildAt(tmpClip, 0);
}

function onBtnClearClick(e:MouseEvent):void {
	for ( var i:int = this.numChildren - 1 ; i >= 0; --i ) {
		var tmpClip:DisplayObject = DisplayObject( this.getChildAt( i ));
		if ( tmpClip.name == "tmpClip" ) {
			this.removeChild( tmpClip );
			tmpClip = null;
		}
	}
}

function CopyDisplayObj(target:DisplayObject, autoAdd:Boolean = false):DisplayObject {
	var targetClass:Class = getDefinitionByName(getQualifiedClassName(target)) as Class;
	var duplicate = new targetClass;
	
	if (autoAdd && target.parent) {
		target.parent.addChild(duplicate);
	}
	return duplicate;
}

function DuplicateDisplayObj(target:DisplayObject, autoAdd:Boolean = false):DisplayObject {
	// create duplicate
	var targetClass:Class = Object(target).constructor;
	var duplicate:DisplayObject = new targetClass();

	// duplicate properties
	duplicate.transform = target.transform;
	duplicate.filters = target.filters;
	duplicate.cacheAsBitmap = target.cacheAsBitmap;
	duplicate.opaqueBackground = target.opaqueBackground;

	// add to target parent's display list
	// if autoAdd was provided as true
	if (autoAdd && target.parent) {
		target.parent.addChild(duplicate);
	}
	return duplicate;
}




歡迎您留言與分享!(Welcome for comments or sharing!)

Related Post:

Tagged on: , ,