AS3 Timeline

项目地址:as3timeline

本意是想做个表现录像回放的时间轴.API按照Flash IDE的JSFL来设计的.所以如果大胆幻想一下,也许可以做出个Flash的Flash动画编辑工具.

as3 timeline

发表在 as3, flash, jsfl | 留下评论

用TweenLite制作窗口拖动特效(1)

本教程讲解窗口(图片)拖动特效的制作.
主要是利用drawTriangles绘制变形位图,用TweenLite实现移动过程的缓动.

先看下最终的效果(鼠标点击拖动面板):

Get Adobe Flash player

大体的思路是:把图片矩形分段,把矩形的运动分解为各个顶点的运动,结合各个顶点利用drawTriangles绘制变形位图,最后用TweenLite加入缓动效果.
null
接下来逐步讲解:

1.图片矩形的分段

如果图片位置是pos,要分的段数是segments,取得分段后的顶点,我们通过buildSegments方法来实现.具体如下:

		/**
		 * 对面板分段, 返回顶点(Point)的二维数组
		 */
		private function buildSegments(pos : Point) : Array
		{
			var pts : Array = new Array();

			// 分段后平均每段的宽/高
			var unitW : Number = this.panel.width / segments;
			var unitH : Number = this.panel.height / segments;

			// 遍历, 把分段后的顶点存放在pts数组(二维)中.
			for (var col : int = 0; col < segments + 1; col++)
			{
				pts[col] = new Array();
				for (var row : int = 0; row < segments + 1; row++)
				{
					pts[col][row] = new Point(pos.x + col * unitW, pos.y + row * unitH);
				}
			}

			return pts;
		}

通过buildSegments方法,取得分段后的顶点,并以二维数组([列,行])的形式保存下来.

2.drawTriangles绘制图片

drawTriangles是FP 10后Graphics增加的方法.可用来绘制三角形,并进行贴图.它提供三个参数

  • vertices(Vector.<Point>),三角形的顶点,顶点的数据形式不是Point而是x,y的数值(所以长度必定是6的倍数).
  • indices(Vector.<int>),三角形的边,根据顶点在数组中的索引,两个索引表示一条边.
  • uvData(Vector.<Number>),三角形顶点对应的贴图比例.

把面板分段后,循环绘制出每一个网格矩形.每一个矩形有四个顶点(tl,tr,br,bl),切分成两个三角形来绘制:
null
绘制(render)方法具体如下:

		/**
		 * 绘制面板
		 */
		public function render() : void
		{
			var g : Graphics = this.graphics;
			g.clear();
			var tl : Point, tr : Point, bl : Point, br : Point;
			// 使用drawTriangles绘制分段矩形
			var vertices : Vector. = new Vector.();
			var indices : Vector. = new Vector.();
			var indiceIndex : int;
			var uvData : Vector. = new Vector.();
			var seg : Number = segments;
			for (var col : int = 0; col < segments; col++)
			{
				for (var row : int = 0; row < segments; row++)
				{
					// 单个矩形的四个顶点
					tl = pts[col][row];
					tr = pts[col + 1][row];
					br = pts[col + 1][row + 1];
					bl = pts[col][row + 1];

					vertices.push(tl.x, tl.y, tr.x, tr.y, br.x, br.y, bl.x, bl.y);

					var nextU : Number = (col != segments - 1) ? (col + 1) / seg : (1 + 1 / this.panel.width);
					var nextV : Number = (row != segments - 1) ? (row + 1) / seg : (1 + 1 / this.panel.height);
					uvData.push(col / seg, row / seg, nextU, row / seg, nextU, nextV, col / seg, nextV);

					indices.push(indiceIndex, indiceIndex + 1, indiceIndex + 3, indiceIndex + 1, indiceIndex + 2, indiceIndex + 3);
					indiceIndex += 4;
				}
			}
			g.beginBitmapFill(new IMAGE().bitmapData);
			g.drawTriangles(vertices, indices, uvData);
			g.endFill();
		}

这里有个问题,我在实际书写drawTriangles的uvData并测试最终效果时,发现右边缘与下边缘都是少一个像素的.所以在遍历到边缘(col == segments – 1 || row == segments – 1)时, 把这一个像素转成百分比(1/panel.width, 1/panel.height)加到uv中.

3.实现鼠标拖动

鼠标拖动的实现主要是侦听处理鼠标的三个事件:MOUSE_DOWN,MOUSE_UP,MOUSE_MOVE

		/**
		 * 侦听鼠标交互
		 */
		private function buildInteractor() : void
		{
			this.stage.addEventListener(MouseEvent.MOUSE_DOWN, mouseEventHandler);
			this.stage.addEventListener(MouseEvent.MOUSE_UP, mouseEventHandler);
		}

		/**
		 * 处理鼠标事件,实现拖动
		 */
		private function mouseEventHandler(event : MouseEvent) : void
		{
			switch(event.type)
			{
				case MouseEvent.MOUSE_DOWN:
					this.mouseOffset = new Point(this.mouseX - this.posPt.x, this.mouseY - this.posPt.y);
					// 开始拖动
					this.stage.addEventListener(MouseEvent.MOUSE_MOVE, mouseEventHandler);
					break;
				case MouseEvent.MOUSE_UP:
					// 结束拖动
					this.stage.removeEventListener(MouseEvent.MOUSE_MOVE, mouseEventHandler);
					break;
				case MouseEvent.MOUSE_MOVE:
					this.move(this.mouseX - this.mouseOffset.x, this.mouseY - this.mouseOffset.y);
					break;
				default:
			}
		}

在鼠标移动时,调用move方法传递目标位置,移动面板.看下一步.

4.移动面板,实现缓动

面板移动时,我们先把各个顶点的目标位置通过buildSegments计算出来,然后遍历对每个顶点添加缓动.每个顶点的移动时间需要不一样(如果一样的话,最终效果还是整个面板在平移),这里顶点的移动时间根据它与鼠标的距离来计算得出.

		/**
		 * 实现移动动过程缓动
		 */
		private function move(tx : Number, ty : Number) : void
		{
			this.endPt = new Point(tx, ty);

			// 计算各个分段顶点的目标位置
			var endPts : Array = this.buildSegments(this.endPt);

			// 创建缓动引擎
			this.engine = new TimelineLite({onUpdate:this.render, onComplete:this.onMoveComplete});

			// 遍历, 把分段后的顶点存放在pts数组(二维)中.
			for (var col : int = 0; col < segments + 1; col++)
			{
				for (var row : int = 0; row < segments + 1; row++)
				{
					var end : Point = endPts[col][row];
					var time : Number = Math.sqrt((end.x - mouseX) * (end.x - mouseX) + (end.y - mouseY) * (end.y - mouseY)) / 400;
					this.engine.insert(new TweenLite(this.pts[col][row], time, {x:end.x, y:end.y}));
				}
			}

			// 播放缓动
			this.engine.play();
		}

注意代码在TimelineLite.onUpdate时执行render重新绘制面板.

源码下载

源码打包,包里不含有TweenLite库.

后续

好了,初步完成,还有很多优化的空间,下回继续.

发表在 as3, flash | 标签为 , | 留下评论

FlashFirebug 3.0

FlashFirebug 3.0已经推出!
新版本重写显示对象树面板,整合了FlashInspector,也修复了大量的bug。
除此之外,FlashFirebug 3.0增加了专业版,专业版多出的功能是控制台(Console),通过控制台你可以运行AS3代码。我想对绝大多数用户来说非专业版的功能已经够用了。
更多信息请访问:http://www.o-minds.com/products/flashfirebug

发表在 as3, firefox | 标签为 | 一条评论

HtmlText及打字效果

HtmlText目的是方便对TextField.htmlText字符串进行分割,如下图:

可以直接利用TextField.text来的字符索引来定位分割,但返回的字符串仍保留html的所有标签。使用方法如下:

var html:HtmlText = new HtmlText('Hello <b>world</b>!');
//输出<b>world</b>,而不是<b>wo
trace(html.slice(5, 10));

一个简单的应用:HtmlText实现支持html的打字效果:

Get Adobe Flash player


源码下载:
HtmlText.zip

发表在 as3, flash | 标签为 , , , | 留下评论

计算网格中直线经过的格子

关于在位图上像绘制直线的算法,可以参见:http://free.pages.at/easyfilter/bresenham.html。但是不同于在位图上绘制直线,需要的是:一条直线经过哪些格子。

  1. 假设有p0,p1两个点,位置如下图:
  2. 我们很容易得到连线的方程。首先我们按照在x上取整递增,很容易计算出x=1, 2, 3, 4…时y的值是多少。
  3. 然后对y值取整,所得到(x1,y1),(x2,y2),(x3,y3)…肯定是连线过的格子。
  4. 但是我们遗漏了这种情况,左上格也是连线经过的格子,但由于我们只在x轴上进行取整递增运算,没有被考虑在内。
  5. 在(2)时已经可以知道A点坐标,我们可以斜率来判断连线是否经过上面一格。如果“蓝色线的斜率小于p0-p1的斜率”,说明连线经过了上面一格。
  6. 利用这种方法,可以轻松计算出连线经过的所有格子。

AS3实现的demo:
Get Adobe Flash player

源码:


/**
* 返回网格中两个点,连线经过的格子。
* @see http://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm
*/
public static function determineTouchedTiles(p0:Point, p1:Point):Vector.
{
var touched:Vector.=new Vector.();

var x0:Number=p0.x;
var y0:Number=p0.y;
var x1:Number=p1.x;
var y1:Number=p1.y;

var steep:Boolean=Math.abs(y1 - y0) > Math.abs(x1 - x0);
if (steep)
{
x0=p0.y;
y0=p0.x;
x1=p1.y;
y1=p1.x;
}

if (x0 > x1)
{
var x0_old:Number=x0;
var y0_old:Number=y0;
x0=x1;
x1=x0_old;
y0=y1;
y1=y0_old;
}

var ratio:Number=Math.abs((y1 - y0) / (x1 - x0));
var mirror:int=y1 > y0 ? 1 : -1;

for (var col:int= Math.floor(x0); col < Math.ceil(x1); col++)
{
var currY:Number=y0 + mirror * ratio * (col - x0);

//第一格不进行延边计算
var skip:Boolean = false;
if(col == Math.floor(x0)){
skip = (int(currY) != int(y0));
}

if(!skip){
if (!steep)
{
touched.push(new Point(col, Math.floor(currY)));
}
else
{
touched.push(new Point(Math.floor(currY), col));
}
}

//根据斜率计算是否有跨格。
if ((mirror > 0 ? (Math.ceil(currY) - currY) : (currY - Math.floor(currY))) < ratio)
{
var crossY:int = Math.floor(currY) + mirror;

//判断是否超出范围
if(crossY>Math.max(int(y0), int(y1)) || crossY

//跨线格子
if (!steep)
{
touched.push(new Point(col, crossY));
}
else
{
touched.push(new Point(crossY, col));
}
}
}

return touched;
}

发表在 as3 | 标签为 , , | 留下评论

JSFL类示意图

值得收藏:

该图片截自:http://staff.lero.ie/pleuss/docs/Pleuss07_MDDandAuthoringTools.pdf

发表在 flash, jsfl | 留下评论

FlashInspector、FlashFirebug与Flash Builder的概要分析工具冲突

FlashInspector与FlashFirebug(2.0)和Flash Builder的概要分析工具(Profiler)都会设置mm.cfg的PreloadSWF参数, 所以会产生冲突, 导致Flash Builer的Profiler失效. 如果遇到这种情况, 可以先禁用FlashInspector和FlashFirebug(2.0), 或者为Firefox建个新的Profile.

发表在 as3, firefox | 标签为 , , , | 2 条评论

FlashInspector 0.2.3更新

Flash Inspector更新至0.2.3. 加入了我最期待的一个功能:与FlashFirebug整合. FlashFirebug是对Flash开发很有用的一个调试工具. 但是使用它必须在swf里面先导入FlashFirebug的一些类. 通过Flash Inspector就不必这么麻烦了.

Flash Inspector采用了插件机制, 对FlashFirebug的支持, 其实就是编写一个插件负责与FlashFirebug交互. 要使用这个插件需要Firefox安装:Firebug(对于使用Firefox的前端开发者这应该是必备了吧?), FlashFirebug, Flash Inspector.
安装之后, 在状态栏上右击Flash Inspector的图标, 勾选”FlashFirebug”. 刷新一下页面.

不过FlashFirebug本身是针对自主项目的, 要求swf必须是”allowScriptAccess”的. 所以网页的swf不满足这个条件就没办法使用Flash Inspector的这个功能. Flash Inspector会尝试10次连接Flash Firebug, 如果连接失败, 会在左上角的工具栏中显示一个tip.

这次更新也加了对Firefox 4的支持.

发表在 as3, firefox, flash, tInspector | 标签为 , , | 13 条评论

关于在FlashInspector主页找不到其它版本的问题

现在访问Flash Inspector的主页,只能看到FlashInspector 0.1.7版本。其它版本不是被删除了,而是因为被禁用而没有列出来。

下面是Flash Inspector的组件管理面板的截图,可以看到很基本上所有版本都被禁用了。

Mozilla(应该是在上周)修改了关于附加组件的策略,Flash Inspector所有未审核过的版本全部被禁用了。Flash Inspector 0.1.7是Mozilla唯一审核过的一个版本。坦白讲这挺挫伤对Flash Inspector开发的积极性,因为Flash Inspector被审核很难通过,而一个不为人知不为人用的东西,做了有虾米意义呢?

关于Firefox大量组件的审核,我非常理解Mozilla,想象得出来他们的工作量非常的大。
Flash Inspector很难通过审核的原因:Flash Inspector包含了三个的swf文件,提交新版本后,最快一周内,开始接受审核,审核人员可以很容易看到JS、文本文件的哪些代码修改、增减,但是只能看三个swf文件发生了改变,为了保证这些文件是安全的,我会收到一封邮件要求提供这三个swf文件的源代码,当然我立马就给发了过去,啥子时候能审核通过真是不知道。

发表在 firefox, tInspector | 2 条评论

FlashInspector 0.2.2更新

FlashInspector 0.2.2,更新主要包括:

  • 整合Transform3DTool,这样Flash Inspector就支持对显示对象进行3D变形(transform)了。不过遗憾的是Transform3DToolFlash Player 10下存在严重Bug,在Flash Player 10.1下没问题。这个bug还没着手解决,尚不知道具体原因。总之,如果你不想把FirefoxFlash Player升级到10.1,也就没有必要更新FlashInspector 0.2.2了。
  • 设置Firefoxdom.ipc.plugins.enabled.npswf32.dllfalse,这个属性默认是为true,设置成false是为了防止Flash Player报错时,Firefox整个假死。详见
  • 去除as3swf的使用。as3swf真的很给力,但它体积宠大,而且Flash Inspector用到as3swf的只有SwfInfoView这个插件,解析swf的尺寸、背景色等信息,杀鸡焉用牛刀?为此Flash Inspector编写自身的swf解析类。

最后,希望FlashInspector对你有用。

发表在 as3, firefox, flash, tInspector | 8 条评论