[Flash10+3D] 简单的、清晰的卡片翻转效果

这几天在做的一个项目需要做一个卡片翻转效果,实践了一下Flash 10的新的3D功能。果真是方便至极,所有的可视化对象现在都有了3D相关的属性,只需要设置rotationY变化,就可以做出很炫的翻转效果了。但是我发现,经过3D变换后的对象,都会被Flash转成位图缓存的方式显示,这样原先清晰的一些文字、图片等内容,就会显得比较模糊,演示:(需要安装 Adobe Flash Player 10 才能看到效果) 第一面的文字本来是清晰的,翻转一遍之后就模糊了。Google了好久都没有找到解决方案,抓狂。。后来突然想到,是不是可以这样,将要变回清晰的对象换个清晰的父对象?实验了一下,果然可行,大喜!好像我太out了吧,直觉告诉我,在Flash9+Papervision3D的年代,大家应该都已经知道这个方法的了,但是我确实没有找到……现在将代码重新整理了一遍,记录下来,也许对大家有所帮助。 先看看效果: 主要的类: ?
/**
 *
 * @author qhwa, , qhwa@163.com
 * This class is a sample of Flash-10-3D-flipping,
 * that can keep faces clear, not as fuzzy as
 * default.
 *
 * 这个类演示了如何使用Flash10自带的3D功能创建一个
 * 简单的卡片翻转效果,同时保持文字和其他内容的
 * 清晰
 *
 */

package qhwa.twosideflip
{
	import flash.display.DisplayObject;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.text.TextField;
	import flash.text.TextFieldType;
	import gs.easing.Back;
	import gs.TweenLite;

	/**
	 * ...
	 * @author ...
	 */
	public class Card extends Sprite
	{
		[Embed(source='../../../lib/goodbyewow02.jpg')]
		private var FrontFace:Class;

		[Embed(source='../../../lib/goodbyewow04.jpg')]
		private var BackFace:Class;

		private var fFace:Sprite;
		private var bFace:Sprite;
		private var cleanObj:Sprite;
		private var dirtyObj:Sprite;

		public function Card()
		{
			if (stage) init();
			else addEventListener(Event.ADDED_TO_STAGE, init);
		}

		private function init(e:Event = null):void
		{
			removeEventListener(Event.ADDED_TO_STAGE, init);
			// entry point

			var frontBg:DisplayObject = new FrontFace();
			var backBg:DisplayObject = new BackFace();
			frontBg.x = backBg.x = - frontBg.width / 2;
			frontBg.y = backBg.y = - frontBg.height / 2;
			fFace = new Sprite();
			bFace = new Sprite();
			fFace.addChild(frontBg);
			bFace.addChild(backBg);
			//背面需要额外处理一下,
			//翻转过来,并且暂时隐藏
			bFace.scaleX *= -1;
			bFace.visible = false;
			bFace.buttonMode = fFace.buttonMode = true;

			//测试的文字
			var testTF:TextField = new TextField();
			testTF.width = 400;
			testTF.height = 200;
			testTF.textColor = 0xFFFFFF;
			testTF.htmlText = "验证码是防止被机器人恶意灌水的一个方法,"+
				"产生一个只有服务器才知道的信息(例如一个单词、数字等)," +
				"在客户端浏览器中以机器人不能分析的方式(通常是图片)出现," +
				"作为判断机器人和真人的一个依据。一般是在服务器端生成图片," +
				"由用户在文本框输入看到的文字。";
			testTF.appendText(testTF.text);
			testTF.selectable = true;
			testTF.multiline = true;
			testTF.wordWrap = true;
			testTF.x = frontBg.x + 10;
			testTF.y = frontBg.y + 200;
			testTF.type = TextFieldType.INPUT;
			fFace.addChild(testTF);

			cleanObj = new Sprite();
			dirtyObj = new Sprite();

			dirtyObj.addChild(fFace);
			dirtyObj.addChild(bFace);
			addChild(dirtyObj);
			addChild(cleanObj);

			addEventListener(MouseEvent.CLICK, clickHandler);

		}

		private function clickHandler(e:MouseEvent = null):void
		{
			// 修改文字时不动
			if (e.target is TextField) return;

			if (e.target == fFace || e.target.parent == fFace)
			{
				// flip to back
				dirty();
				TweenLite.killTweensOf(dirtyObj);
				TweenLite.to( dirtyObj, 1, {
					rotationY:180,
					ease: Back.easeOut,
					onComplete: cleanBackFace,
					onUpdate: update
				} );
			} else if (e.target == bFace || e.target.parent == bFace) {
				// flip to front
				dirty();
				TweenLite.killTweensOf(dirtyObj);
				TweenLite.to( dirtyObj, 1, {
					rotationY:0,
					ease: Back.easeOut,
					onComplete: cleanFrontFace,
					onUpdate: update
				} );
			}
		}

		/**
		 * 检查应该显示哪个面
		 */
		private function update():void
		{
			bFace.visible = dirtyObj.rotationY > 90 && dirtyObj.rotationY < 270;
			fFace.visible = !bFace.visible;
		}

		/**
		 * 清晰化封面
		 */
		private function cleanFrontFace():void
		{
			if (dirtyObj.contains(fFace))
			{
				dirtyObj.removeChild(fFace);
				cleanObj.addChild(fFace);
			}
		}

		/**
		 * 清晰化背面
		 */
		private function cleanBackFace():void
		{
			if (dirtyObj.contains(bFace))
			{
				dirtyObj.removeChild(bFace);
				cleanObj.addChild(bFace);
				bFace.scaleX *= -1;
			}
		}

		/**
		 * 封面和背面都放入dirty容器,进行旋转操作
		 */
		private function dirty():void
		{
			if (cleanObj.contains(fFace) || cleanObj.contains(bFace))
			{
				var face:DisplayObject = cleanObj.getChildAt(0);
				cleanObj.removeChild(face);
				dirtyObj.addChild(face);
				if (face == fFace)
				{
					dirtyObj.swapChildren(face, bFace);
				} else {
					bFace.scaleX *= -1;
				}
			}
		}

	}

}
下载源文件 (source)