Archive for the ‘flex’ Category.

UIComponent之currentStateChange事件

在使用State的时候,我总是会选择enterState和exitState事件来处理state切换问题(enterState总是在state切换完毕再抛出,这点很便利),可是最近发现一问题,enterState和exitState实际是抛出FlexEvent对象,此对象不包含上一个state和请求的state的信息,也就是说,你也不会知道你是从哪个state切换过来的,对于某些特别的request来说不是很爽。

于是我查了下UIComponent的源码,发现UIComponent带有两个很好用的事件

  • currentStateChange
  • currentStateChanging

在UIComponent的commitCurrentState方法(private)里,还能找到这两个事件,以及enterState,exitState抛出的顺序:

  1. currentStateChanging
  2. exitState
  3. enterState
  4. currentStateChange

从这里不难发现flex framework对于state的处理机制,首当其冲便是currentState property,它存储着state信息。切换的时候,首先抛出currentStateChanging事件,说明切换开始,然后执行“移除”当前state,抛出exitState(至此state被移除),然后切换到新的state,完成后抛出enterState,接着抛出currentStateChange事件,currentState修改完毕。

并且我们可以注意到,currentStateChange抛出的是StateChangeEvent事件对象,此对象带有oldState和newState property,恰好弥补了enterState和exitState的不足。

分页组件

以前写的一段Flex分页组件,可以复用。样式如下,左右各有一组”<<”和”<”,分别表示跳到第一页和前一页(相对应的,跳到最后一页和后一页),屏幕上页面数字只会显示7个,功能很基本。

fy

fy2

fy3

这套组件主要是用到了LinkButton和Repeater。

<!-- page -->
<mx:HBox id="paginationbox" width="100%" height="24"
		 verticalAlign="middle" horizontalGap="0"
		 visible="false">
	<mx:Label text="PAGES: "/>
	<mx:Spacer width="3"/>
	<mx:LinkButton label="&lt;&lt;"
				   styleName="pageLinkBtn"
				   enabled="{_curr_page_index!=0}"
				   click="showImagesInList()"/>
	<mx:LinkButton label="&lt;"
				   styleName="pageLinkBtn"
				   enabled="{_curr_page_index &gt; 0}"
				   click="showImagesInList(_curr_page_index-1)"/>
	<mx:Repeater id="prepeater"
				 dataProvider="{_pages}"
				 count="7"
				 startingIndex="{(_curr_page_index-3 &lt; 0)?0:(_curr_page_index-3)}">
		<mx:LinkButton label="{(prepeater.currentIndex+1).toString()}"
					   enabled="{int(prepeater.currentIndex) != _curr_page_index}"
					   styleName="pageLinkBtn"
					   click="showImagesInList(event.currentTarget.repeaterIndex)"/>
	</mx:Repeater>
	<mx:LinkButton label="&gt;"
				   enabled="{_curr_page_index &lt; _pages.length-1}"
				   click="showImagesInList(_curr_page_index+1)"
				   styleName="pageLinkBtn"/>
	<mx:LinkButton label="&gt;&gt;"
				   enabled="{_curr_page_index != _pages.length-1}"
				   click="showImagesInList(_pages.length-1)"
				   styleName="pageLinkBtn"/>
</mx:HBox>

style比较简单

.pageLinkBtn
{
	paddingLeft:0;
	paddingRight:0;
	paddingTop:0;
	paddingBottom:0;
}

升级Flex sdk 带来的错误一例

错误信息:

VerifyError: Error #1053: Illegal override of FlexModuleFactory in mx.core. FlexModuleFactory. at global$init()

看样子就是跟Module相关的,包括从CSS编译过来的SWF。这个问题是由Flex sdk升级导致,需要使用新的sdk重新编译Module和SWF,这样载入进来才“合拍”。完了不要忘了清空缓存再测试

Degrafa的Bezier源码浅析(一)

先解释下Bezier曲线:

http://en.wikipedia.org/wiki/Bézier_curve

Degrafa是一套很强大的图形算法类库,并且开源,对Bezier曲线的绘制提供了很好的支持。说起Bezier曲线,其实就是Photoshop和flash里常用的钢笔工具啦,主要就是用来绘画路径或者绘画不规则图形。前者的应用领域非常广泛,比如使图形沿着路径运动,或者按路径不规则排列图形(具体一例就是扭曲的美术字布局)。这些都会用到Bezier曲线。

Degrafa提供的tutorial不是很完备,很多时候为了扩展应用不得不看源码。我这里只就Bezier相关的处理过程分析一下。

Degrafa下面的类非常之多,跟Bezier相关的主要有:

  • com.degrafa.geometry.splines.BezierSpline
  • com.degrafa.geometry.CubicBezier

两者都继承自com.degrafa.geometry.Geometry。很多图形库都有着类似的继承体系,Geometry作为一个基础的图形类,下面还有很多经过定义的不同种类的图形。

CubicBezier看字面意思,是一个三次贝塞尔曲线,事实上确实如此,它有四个点(start,end,2 control points)控制,其实也就是wiki上的那个图形

而BezierSpline跟真正的钢笔工具非常像,它由一系列点和control points来控制一整条曲线。这里最好看它的注释:

The BezierSpline can be used for drawing of a smooth curve through
multiple points, with some shape control over the curve via a tension
parameter. It may also be used for general path animation with tension
control, optional closed-path control, and velocity control
(arc-length parameterization).

乍看一下,它好像就是若干个CubicBezier的组合,其实关系不是很近。BezierSpline内部确实用到了CubicBezier对象(源码的第一行private var _bezier:Array),它是用来管理三次bezier曲线段的(BezierSpline包括很多的段)。

在使用BezierSpline曲线之前,需要提供一系列的点(钢笔工具的点类似)。使用到的property包括:

  • points
  • data

两者实质相同形式不同而已。

绘画曲线都使用draw方法,这个方法是由Geometry定义,并由它的子类重写的(典型的继承体系)。BezierSpline和CubicBezier都有类似的draw定义方式:

/**
* Begins the draw phase for geometry objects. All geometry objects
* override this to do their specific rendering.
*
* @param graphics The current context to draw to.
* @param rc A Rectangle object used for fill bounds.
**/
override public function draw(graphics:Graphics,rc:Rectangle):void{	

	//re init if required
 	if (invalidated) preDraw(); 

	//init the layout in this case done after predraw.
	if (_layoutConstraint) calculateLayout();

	super.draw(graphics, (rc)? rc:bounds);

}

preDraw在这个体系里非常重要,是用来在绘画之前计算各个点的位置,就像我们使用graphic那样定义好MoveTo和lineTo,所不同的这里会用到很多算法。与draw一样,preDraw在Geometry里定义在子类里重写,每个子类都有不同的方法。比如BezierSpline:

/**
* @inheritDoc
**/
   override public function preDraw():void{
   	if( invalidated ){

        	if(!points.length){return;}

        	_assignControlPoints();

        	//add a move to for the first item.
        	commandStack.length=0;

	//add a MoveTo at the start of the commandStack rendering chain
	commandStack.addMoveTo(points[0].x,points[0].y);

	var cubic:CubicBezier;

        //todo not sure were this extra one is coming from yet.
        //re:: - 1 on the count
        for( var i:uint=0; i<_bezier.length-1; ++i ){

        	cubic = _bezier[i];

        	commandStack.addCubicBezierTo(cubic.x0,cubic.y0,cubic.cx,
       	cubic.cy,cubic.cx1,cubic.cy1,cubic.x1,cubic.y1,1);

  	}

     		invalidated = false;
}
	    }

挖到这里,基本上快看到bezier算法在Degrafa里怎么实现的了,关键就是这个commandStack,字面意思:命令退栈,命令集合。

localhost下模拟慢网速

Flash IDE 可以为调试的swf模拟网速来测试进度条。如果是Flex builder呢,似乎是没有的,不过千万别在这个问题上钻牛角尖,因为这实际上是本地服务器的职责,而不是flex builder该干的工作(flex builder编译完成并启动页面后就结束任务了)。

在这种情况下要为flex模拟慢网速的话,就要使用proxy工具了,我这里推荐ServiceCapture,当然很多http检测工具都带有模拟网速的功能,我选serviceCapture除了它能检测http,还能读出trace和AMF协议,简直是Flash专用工具

首先你需要安装serviceCapture for firefox 插件,让它“干预”firefox上的调试。

sc_1

sc_2

然后所有在firefox里发生的http和AMF连接都会被记录下来,serviceCapture “中转”了firefox的请求,这样就能人为的拖慢网速。

sc_3

避免try catch,提升Flash性能

在一些实时性能要求比较高的应用中,如3D,try…catch处理错误会严重的影响性能和执行效率,应该尽量使用判断语句来代替。为此我有个实验。

if (theOldIndex >= 0 && theOldIndex < this._cache_pop_yw_zws.length)
{
	_gra.lineStyle(1, 0xffffff);
	_gra.beginFill(colorFront);
	_gra.drawCircle(theCachedArr[theOldIndex].x, theCachedArr[theOldIndex].y, 6);
	_gra.endFill();
}

这里主要是为了不让theOldIndex溢出造成错误,如果每次ENTER_FRAME都是用try catch来判断,大概用getTime测试的执行时间会大上一倍多,太杯具了。因此尽量要预见可能出现的问题,有时情愿写code麻烦点。我想这也是c可以长盛不衰的原因吧。

SlideshowPro for flash

SlideShowPro for flash is a photo and video slideshow component that can be embedded in Flash. It is flexible and easy-customized. We have used it in our photo gallery flash and it works well.

check it here. It’s not free:)

the configuration is very simple, you can just open component panel in Flash and drag-drop SlideShowPro on stage. The configuration panel looks like:

slideshowpro component panel

slideshowpro component panel

SlideShowPro will read xml file for configuration, which specify images and their path. here is demo of xml:

<?xml version="1.0" encoding="UTF-8"?>
<gallery>
  <album title="Samples" description="XXXXX" 
         lgPath="path/of/images/">
	<img src="001.jpg" /> 
    <img src="002.jpg" />
    <img src="003.jpg" />
    <img src="004.jpg" />
    <img src="005.jpg" />
  </album>
</gallery>

flash游戏中的数学问题

LongLongAgo,在做泡泡龙游戏的时候,发现数据结构的好处。使用树结构的数学模型可以清晰的描述逻辑处理方式。比如在判断是否有球掉落的时候,见下图,就可以用这样的数学语言描述:“对某个球而言,不存在一条路径到达root”。root就是最顶层。

泡泡龙

泡泡龙

如果这样的球存在的话,就说明它是“浮空”的,也就是说可以掉下来了。

这类的数学描述在很多领域都用过,记得flash的垃圾回收机制么,原来使用计数法来判断一个对象要不要被消灭,如果用在displayObject树结构里就不够了,因为它们可以相互引用,于是,用上面所说的数学描述就成了很好的补充,跟泡泡龙的原理类似,如果有一个displayObject不能到达root的话,它就脱离了显示树,就该被消灭,而不用管计数是多少。

回到泡泡龙的问题上来,一个被发射上来的球可以看成一个根节点,当它被打到一堆球当中的时候,一个树结构就形成了:以这个新球为根,周围的六个球为第一层子节点(可能某些是空,或者重复应用,需要剔除),然后使用广度优先或者深度优先遍历来查找“通往root的路径”,再加上些优化,就能实现这种数学描述,从而完成“掉落”这个游戏功能。

数学在flash游戏中无处不在。此乃往事,特此笔记。

快来用Git

Git这个版本控制工具已经很有名气了,不知道的可以去网上查查。在我看来,它最大的好处是小巧,相比于svn,Git的仓库可以“搬来搬去”,是分布式的。你的本地可以保留一份工作“仓库”,这意味着,即使在离线情况下依然可以执行commit等版本控制操作,如果“仓库”在本地的话,commit非常之快速了。

我把Git当作“一个人的软件工程”之必备工具,当你一个人写一个project并且不需要服务器的时候,Git这类分布式的版本控制工具不正好派上用场么。

官方网站见这里

下面我来简要的描述下Git的用法:

  1. 上官网下载Git,根据你的操作系统。Git应该有绿色版本,操作方式是command-line的,不习惯的朋友可以找找GUI版本。
  2. 打开git-cmd.bat进入命令行模式
  3. 进入你的source code文件夹,先来建立一个git仓库。命令是git init。git的命令都是类似格式:git xxx。
  4. 仓库建立好后,此文件夹下的东西就属于工作区了,但是文件还没有纳入版本控制,需要使用git add 命令来纳入。
  5. git status是最常用的命令了,查看当前工作区文件状态,比如有没有新文件,有没有修改过等等。也会有操作提示。
  6. git help查看命令列表吧。

Flex builder 配合 FlashDevelop开发模式

每次谈到Flex builder和FlashDevelop这两个工具总不免比较一番,其实两者各有优点为什么不互补一下呢。事实上我在实践过程中,觉得有些情况下两个配合着用非常不错。FlashDevelop有轻便的优势,代码提示很好,而Flex builder支持Flex framework,支持可视化开发,搭建UI快捷编码量少。

什么时候配合着用比较好呢。那就是开发AS类库,类库用FlashDevelop开发,轻便快捷,而测试使用Flex builder,快速构建UI来显示效果,提供参考。

通过观察FlashDevelop project的文件夹可以发现,基本上FlashDevelop和Flex builder的布局是差不多的,source code放在src里,编译文件放bin,类库放lib等等。于是就有两种配合方式可供参考:

  • 叠在一块儿。先用FlashDevelop建一个project,然后Flex builder也建在同一个位置。
  • 分开建project。Flex builder使用external source path来链接类库代码。

显然第二种方式更好,可以有效的将测试代码和类库代码分开。