Flashlight

Flash, Game, Web

Flash在某些多标签浏览器中的“伪沙箱”问题

sandbox

在Flash播放器运行时,将不同来源的资源划分到独立的沙箱(sandbox)内,不同沙箱之间不能彼此操作数据(除非目标沙箱做过一些设置,授权其他沙箱可访问),这就是Flash的跨沙箱问题。当Flash文件(.swf) 和页面(.html)不在同一个域名下时,如果不经过Flash内部声明System.allowDomain,html无法访问flash定义的接口;不经过html设置allowScriptAccess为’always’,Flash也无法调用页面上的js函数。

那么如果html和flash都设置了互相可以访问,是否Flash和html之间就可以互相访问了呢?理论上是的,然而实际上却不是。破碎的心

Read the rest of this entry »

使用Fiddler提高前端工作效率 (实例篇)

上一篇(介绍篇)中,我们对Fiddler Web Debugger有了简单的接触,也许你已经开始在用Fiddler进行HTTP相关的调试,在这一篇,我们将通过一个实例了解Fiddler的神奇魔法。

在我们前端开发的日常工作中,发现服务器上某个css/javascript文件有问题,需要修改,那真是家常便饭。通常,我们需要将文件进行修改,然后重新发布再验证,这样就很容易影响到生产环境的稳定性。更普遍的做法是,我们在开发环境中修改文件并验证,然后发布到生产环境。虽然安全,却比较繁琐。而利用Fiddler的可以修改HTTP数据的特性,我们就非常敏捷地基于生产环境“修改——验证——发布”。 Read the rest of this entry »

使用Fiddler提高前端工作效率 (介绍篇)

1. Fiddler 是什么?

Fiddler是用C#编写的一个免费的HTTP/HTTPS网络调试器。英语中Fiddler是小提琴的意思,Fiddler Web Debugger就像小提琴一样,可以让前端开发变得更加优雅。

Fiddler是以代理服务器的方式,监听系统的网络数据流动。运行Fiddler后,就会在本地打开8888端口,网络数据流通过Fiddler进行中转时,我们可以监视HTTP/HTTPS数据流的记录,并加以分析,甚至还可以修改发送和接收的数据。Fiddler还提供了清除IE缓存、请求构造器、文本转换工具等等一系列工具,对前端开发工作很有价值。 Read the rest of this entry »

帮助我提升Actionscript 开发效率的一些工具

一个好用的工具不仅仅可以解决问题,还可以提高工作的效率。追求最高效敏捷的开发,是一种精神。在平常工作中,我不断在寻找提高效率的软件,以下是Flash开发时候用到的一些工具,与大家分享一下,拋砖引玉,如果你有更好的,不妨来交流一下。

1.开发环境类

2.帮助、工具书

3.测试类

4.代码管理

5.通用工具

异步+Vector版本的JPEG编码器

业界大牛 Thibault Imbert (bytearray.org) 近日将很常用的JPEGEncoder类用vector类改写了一下,做了一个vector版本的JPG编码类,效率大幅提升。正好,前不久我也已经做了一个vector版本的JPEG编码类,在项目中使用,最近正在整理代码准备分享出来。当然啦,我所做的没有Thibault那么深入,仅仅是把Array换成Vector,所以现在就拿他的版本重新修改了一下,加上了异步功能。

所谓的异步编码,是延时处理代替循环处理。比如写入1000行文字到一个文件内,可以用for/while循环1000次,一次性写入,这就是同步处理;也可以写1行,隔0.5秒再写下一行,再隔0.5秒继续写下一行,这就是异步处理。同步处理的好处是快速,但是对计算机的压力也比较大,在浏览器中使用时,会造成假死,可能会引发稳定性问题。

Vector的效率比Array高了大约4~10倍,但还是不够高,Alchemy或者haxe的效率会更高一些,因为它们使用了Flash10未公开的opcodes接口,可以直接操作一段内存数据。Mateusz Malczakhttp://segfaultlabs.com)就做了一个异步Alchemy版的JPEGEncoder,效果很赞,速度比我vector异步版的要快很多,但是缺少了一些自定义参数设置(在压缩小图片的时候,看上去效率反而不如Vector,其实不然,实际上,这是因为程序中写死了大小2800×2800Alchemy的C源码修改起来也比较麻烦,要用Alchemy重新编译。而且因为编译了整个libjpeg,所以文件体积也比较大,用C重新写一遍所有相关的类可以解决大小问题,但问题也会更加麻烦。看起来,haxe生成的swc应当是最佳选择,正在考虑有空的时候改写一个。 :)

我将这个几个放在一起,来看一下例子吧!(需要安装Flash Player10)

下载 源文件 下载 带有异步压缩功能的vector版JPEGEncoder

关于 Alchemy 和 Haxe:

AlchemyAdobe实验室的一个项目,它的前身是Scott Petersen的“FlaCC (Flash C Compiler)”,目标是让C语言写的类能够被Flash重用。在MAX 2007 大会上,Scott凭借Flash中畅玩Doom一鸣惊人。Alchemy可以将C语言代码变成Flash可用的swc文件。这种方式类似于在C语言里面直接执行汇编语言,效率自然提高很多。目前Alchemy还只是测试项目,但是已经开放了SDK下载,可以编译许多常用的C类库。

Haxe 是传奇的 Nicolas Cannasse 创造的语言。Nicolas 发明了大名鼎鼎的MTASC (Motion-Tween Actionscript Compiler),在AS2.0的时代,改变了AS开发的方式,Flash也进入开源时代。进入AS3.0时代后,Nicolas选择了自己创造一种语言,这种语言吸取了Flash的优点,并且在语言和编译器上做了很多优化,使得效率上大幅度提升,这就是Haxe。时至今日,Haxe已经发展为一个丰富、高效的高级语言,也对Actionscript的发展产生了影响,例如Flash10的Vector,就和Haxe的概念和语法非常相似。

Alchemy公开之后,Nicolas 找到了 Flash播放器中留给Alchemy的未公开的接口,通过这些接口,AS可以直接操作一段内存中的数据。Haxe也使用了这些接口,并称之为Flash Memory,借助Alchemy的接口,Haxe的效率也大为提升。

关于FlashDevelop中使用中文的一些经验

1. 中文乱码问题和解决方案

新安装的 Flashdevelop 打开有中文的文件时,会有乱码现象,如图: snap0024_flashdevelop

手动选择编码为UTF-8格式(File -> encoding -> UTF-8 ),会发现如果汉字是奇数个一起的时候,最后几个字符会变成乱码。这是由于 Flashdevelop 读取文件,没有找到文件内的编码标记,就默认以8bit方式读取,再转回utf-8格式的时候就会出问题。

解决方案: 选择菜单 Tools – 将设置中的 Fallback Codepage 设置为utf-8,这样flashdevelop在不知道文件应该用什么编码的时候,就会以utf-8处理。这里顺便也将其他几个编码设为utf-8,这样就更好了。 snap0026_flashdevelop3

2. 修改默认字体大小

默认情况下中文字比较小,看着会比较累。选择 Tools -> Syntax Color… 就可以修改了。 注意哦,默认只是改编辑AS3 的字体。我就犯了错,拿AS3的设置修改,然后看XML文件的显示效果,结果发现怎么改都没效果 -__-!

我用的是Verdanda/10pt, 最终的效果:

snap0025_flashdevelop2

使用Filereference时的一些注意事项

FileReference用来上传文件,结合FileReferenceList使用,可以弹出一次文件选择框就上传很多个文件,比HTML form形式的友好很多。但是使用的时候,有些地方需要注意的:

  1. 上传文件时,不能增加自定义request header

    这点不同于URLLoader:URLLoader是可以增加自定义头部信息(request header)的,但是敏感的字段是不可以更改的,比如refer、cookie、host等等;而FileReferrence则不可以增加任何自定义头信息,所有自己添加的自定义header,都被播放器悄无声息地忽略掉了,没有任何报错和提示。如果一定要增加字段,只能添加到POST变量中。

  2. 只有IE才能附带浏览器Cookie信息

    在非IE浏览器中,利用FileReference发出的HTTP请求,带的cookie资料都是IE的cookie。即便在Firefox或者chrome中,传送的cookie也是IE的!有的同学说这和默认浏览器设置有关,例如将默认浏览器设为Firefox,那么IE就得不到cookie。但是我测试了一下,发现无论默认浏览器是什么,发送的都是IE的cookie。解决方案暂时是借用JS得到cookie( ExternalInterface.call(“javascript:document.cookie”) ),当作变量post过去。麻烦的是,服务器端也要做相应的调整。这个BUG到目前(2009年4月6日)为止,已经差不多存在了一年了。

  3. 得不到文件的本地路径

    Flash10的Reference可以得到本地文件的二进制文件,但是得不到文件路径(file://…)。这个问题还附带导致了一个问题,FilereferrenceList不能判断出重复选择的文件。就是说第一次弹出文件选择对话框的时候,用户选择了一个文件。过了一段时间再继续浏览文件,又选择了这个文件,这时候Flash是没有办法知道重复选择的。

  4. 不能设置上传的content-type

    可能会让人郁闷的是,这个也没有任何throw/warning报错。

  5. 只支持实际存在的文件的上传下载

    要是要上传一些动态生成的数据到服务器存储,那就用不得Filereference,也看不到上传进度了。

顺便说一下,内存里面的数据,希望上传到服务器保存为文件,可以用URLLoader,URLStream之类的代替。但是FlashPlayer10有个新增的安全性限制,当上传文件的时候,播放器会检查操作是否由用户点击触发。没有点击就上传,会被浏览器阻挡掉请求。播放器判断一个HTTP请求是否是文件上传的依据是form-based-HTML-file-upload规范,有两个标志: 一是content-type含有“ multipart”,例如“multipart/form-data”,“mymultipartxxx”; 二是字段名含有 filename。 满足了这两点,flash播放器就会把这次请求当作文件上传处理,进而检查是否符合安全限制。要防止被阻挡掉也很简单,不要用filename这个关键字做数据的字段名即可。

[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)

专业的Flash相册

因为近期工作的内容很多涉及到Flash相册,这段时间我对网上的Flash相册比较留意,试着整理了一些很好的Flash相册形式。但是我发现这些整理基本上属于多此一举,因为有个提供Flash相册的网站,里面的效果涵盖了我整理的大部分,而且可以很详细地自定义细节!她的名字叫做:PictureTrail

FlashPlayer 10 新功能:Vector

FlashPlayer 10附带的内部类,多了一个vector,它的作用是对数组的数据结构进行优化,相当于一串只能存放指定数据类型的链表。所以在执行效率上,比数组有很大的提升。 Adobe的文档写得很详细,值得一看。他的 forEach, every 方法,很强大。

Performance Optimization WordPress Plugins by W3 EDGE