MouseWheelTrap

用于解决浏览其中鼠标滚动与Flash中冲突的问题,用法:

原理上就是通过AS 3ExternalInterface调用js来禁用浏览器的鼠标滚动事件。不过使用的时候注意,作者的源代码里面是让Stage一直侦听MOUSE_MOVE事件的,这点没有必要,应该修改。

MouseWheelTrap

更新文件避免浏览器缓存的解决方案(基于svn)

问题的存在

一旦项目上线,隔不久发布更新,就会碰到一个问题:如何保证客户端(Flash)加载到的是最新的文件,而不是浏览器中的缓存?

问题的解决

最基本的,想让as3加载文件时忽略浏览器缓存可以是

  • 在URLRequestHeader中添加”no-cache”
  • 在URLRequest中附带一个参数

但显然如果文件在没有发布新版本的情况下,用不着让文件每次加载都忽略浏览器缓存,太浪费了。

那么只要有份数据,列表记录此次发布修改过的文件,让客户端(Flash)每次运行时都加载该列表。当需要加载某个文件时,可以比较这个列表,看是否需要忽略浏览器缓存加载最新文件。

这个机制挺ok的,但是如果客户端错过了一个版本,那么就可能会仍然存在没使用最新文件的问题,如图:

客户端错过了1.0.1版本的发布,没有更新“…/…/1.jpg”和“…/…/2.jpg”,当更新到1.0.3版本时,因为1.0.3版本没有记录“…/…/1.jpg”和“…/…/2.jpg”的修改,所以客户端会从浏览器缓存中加载使用这两个文件最早的版本。

可以看出,只记录更新文件(modified files)的方法不能“安全”地解决这个问题。

为安全解决这个问题,完全可以利用svn,生成一个数据文件,该数据记录每一次发布时每个文件的版本号。在客户端(Flash)运行时,因为每个文件都有个版本号,只要比较服务器与浏览器缓存中的记录文件版本号,即可决定是否忽略浏览器缓存加载最新文件。

如图,客户端(Flash)首先把浏览器缓存中的版本文件和服务器上最新的版本文件都加载进来,一旦运行时需要加载某个文件时,先比较两个版本号是否相同,如果不同则加载服务器上的文件。

动手吧

生成svn status文件

在项目新版本完成,提交到svn时,可以利用svn的命令行工具,把svn status信息输出到xml文件中,供Flash AS3读取解析。svn输出status的信息的命令是:

svn status --xml >> revisions.xml

不过svn status输出产生的xml文件非常详细,文件占得空间较大,作为每次客户端(Flash)运行都需要加载的文件,必需进行压缩。

客户端(Flash)AS3的工作

AS3方面可以编写一个类似RevisionManager的管理类,用来担起各个文件版本管理、比较的重任。

让一切自动化

最后,需要编写一个用于发布的ant脚本,这个ant应该能够:

  1. 利用svn命令行工具输出svn status信息文件
  2. 把版本信息文件进行压缩,这个可以利用JSFL来实现(Flash CS3后JSFL开始更新到E4X 2标准,支持XML)
  3. 把项目新版本提交到svn
  4. 每次发布只要运行下这个ant build.xml即可啦。

最终实现

请参考:更新文件避免浏览器缓存的解决方法(源码)

TortoiseSVN目录下找不到svn.exe

在编写一个Ant的build.xml时,想运行命令行下的svn命令,但在TortoiseSVN安装目录下怎么也找不到svn.exe……

……这个嘛确实是这样的,TortoiseSVN本身没有带上svn.exe,如果需要应该安装Subversion,安装完之后(最好)重启下。我在安装完之后发原本文件的TortoiseSVN图标都没有了,重启完后就OK。

LocalConnection跨域调用注意事项

除了设定必要的allowDomain, allowInsecureDomain之外,注意让LocalConnection.connect(…)名称以下划线开头。
帮助文档它说:

  • 如果 connectionName 字符串不以下划线开头,则 Flash Player 会添加一个包含超级域名称和一个冒号的前缀(例如 myDomain:connectionName)。虽然这可以确保您的连接不会与其它域中具有同一名称的连接冲突,但任何发送方 LocalConnection 对象都必须指定此超级域(例如 myDomain:connectionName)。如果将具有接收方 LocalConnection 对象的 SWF 文件移动到另一个域中,Flash Player 会更改前缀,以反映新的超级域(例如 anotherDomain:connectionName)。必须手动编辑所有发送方 LocalConnection 对象,以指向新超级域。
    这样下来在不同沙箱、域之间的swf就可以通过LocalConnection相互通信了。
  • 如果 connectionName 字符串以下划线开头(例如 _connectionName),Flash Player 不会向该字符串添加前缀。这意味着接收方和发送方 LocalConnection 对象都将使用相同的 connectionName 字符串。如果接收方对象使用 LocalConnection.allowDomain() 来指定可以接受来自任何域的连接,则可以将具有接收方 LocalConnection 对象的 SWF 文件移动到另一个域,而无需更改任何发送方 LocalConnection 对象。

也就是说:不以下划线开头的connectionName会被Flash加上前缀(以区分所在的域),结果就是你在代码里面看到的明明是发送和接收方connectionName完全相同,但就是无法通信。非常的纠结。