Browse > Home > Archive by category 'Flash8/AS2'

| Subcribe via RSS

AS2:通过ExternalInterface使用正则表达式

二月 21st, 2008 | No Comments , 349 views | Posted by flashlizi in Flash8/AS2

AS2中没有正则表达式,虽然有人写过这样的正则类,不过有时候只需少量的正则应用,所以想换个解决方案。因为ExternalInterface的call方法可以调用外部容器中的方法,如果我们的flash是运行在浏览器里的话,那么是否能用javascript来为我们做正则匹配呢?

经过测试,这样的方法是可行的。先看下面的测试代码:

var str:String="www.myDomain.com";
//js代码: 创建和执行regExp方法
var js:String=function regExp(){var str="+str+";return str.replace(/myDomain/g,"RIAidea");}regExp();
//ExternalInterface在浏览器中用javascript的eval方法来执行上面的js代码,并获取返回值
var newstr:String=flash.external.ExternalInterface.call(eval,js).toString();
//在浏览器中弹出窗口显示刚才的返回值
flash.external.ExternalInterface.call(alert("+newstr+"));

把上面代码copy到主时间轴第一帧上,按F12在浏览器中预览(注意文件名不能为Untitled-X,原因请见我上篇文章)。可以看到浏览器会弹出一个窗口,内容为:www.RIAidea.com。这里主要是利用ExternalInterface在浏览器中用javascript的eval方法来执行上面定义包含regExp方法的js代码,并获取正则返回值。最后,再用EI在浏览器中弹出一个窗口,显示刚才获取的返回值。

最后要说明的是,这种偏方有局限性,只能用于浏览器中的flash程序,而且不宜调用复杂的JS方法,请在合适的地方使用。另外,AS3已支持正则,就不需要考虑这样做了,不过,开发flash的web应用的时候,有些地方还是可以使用这样的把外部方法写在AS中的方法的。

谈谈AS中的惰性函数模式(Lazy Function Definition)

八月 31st, 2007 | No Comments , 182 views | Posted by flashlizi in Flash8/AS2

最近看了Peter的Javascript的惰性函数定义模式(Lazy Function Definition)之后,想测试下as下的这种函数模式的效率是否比一般的模式要高。不了解此函数定义模式的朋友可以看看这篇文章的翻译。我做了如下测试:
[code]
//普通函数模式
var num = 0;
function test1() {
return num++;
}
//惰性函数模式
var test2 = function () {
var num = 0;
test2 = function () {
return num++;
};
return num++;
};
getTime1();
getTime2();
function getTime1() {
var time = getTimer();
for (var i:Number = 0; i < 1e+5; i++) {
test1();
}
trace("test1调用次数:" + test1());
trace("普通函数模式:" + (getTimer() - time));
}
function getTime2() {
var time = getTimer();
for (var i:Number = 0; i < 1e+5; i++) {
test2();
}
trace("test2调用次数:" + test2());
trace("惰性函数模式:" + (getTimer() - time));
}
[/code]
在我的机器上的测试结果是普通函数模式运行10万次的时间为825ms左右,惰性函数模式则为790ms左右。从效率上来看,2种模式基本差不多,但惰性模式有它的优点:省略了多余的全局变量num,而且可以防止变量num在函数外部被修改,效率方面也有些提升,还是值得使用的。

然而当我想测试as3下是否也这样的时候,却得到了一个惊人结果:普通函数模式运行100万次的时间为110ms左右,惰性函数模式为320ms左右。显然有一个结论是,在as3下,这种惰性函数模式效率比普通模式低了很多,是否要应用这种函数模式就值得商榷了。但是大家看清楚刚才的测试,as2下是10万次而as3下是100万次。。。它们之间的差距我只能用天壤之别来形容了。呵呵,看到这里,是不是让大家更有信心投入到as3的怀抱中呢?

AS2:让flash捕获用户的快捷键动作

八月 10th, 2007 | No Comments , 209 views | Posted by flashlizi in Flash8/AS2

一般情况下,大家都知道要让flash捕获用户的按键动作可以使用Key类中的onKeyDown、onKeyUp事件以及Key.isDown()、Key.getCode()和Key.getAscii()等方法来实现。这里说一下如何捕获一些组合键(如ctrl+s)?下面是一段捕获ctrl+s快捷键的AS2代码:
[code]var keyListener:Object = new Object();
keyListener.onKeyDown = function() {
trace(Key.getCode());
if (Key.isDown(Key.CONTROL) && Key.getCode() == 83) {
txt.text = "ctrl+s";
}
};
Key.addListener(keyListener);[/code]
在上面代码中,当用户按下ctrl+s快捷键的时候,文本字段txt中的文本就会变成ctrl+s,表示我们已经正常捕获ctrl+s快捷键了。注意:在flash中测试影片(ctrl+enter)的时候一定要在控制中把禁用快捷键勾上,否则测试无效。

但是有些快捷键,如ctrl+C、ctrl+F等,用上面的方法仍然无法捕获。这是因为这些快捷键已经被flash player首先给捕获做其他用途了,当然就无法传到里面的处理函数了。因此我们要告诉flash player释放这些快捷键给AS使用,幸好fscommand函数的trapallkeys命令可以实现这个目的,具体代码为:
fscommand("trapallkeys", true);

这样要实现ctrl+C快捷键,就只要在上面捕获ctrl+s快捷键的AS2代码中加上这条语句就可以了。不过注意这条语句在flash中测试影片(ctrl+enter)的时候是无效的,因为这些快捷键被flash IDE捕获,要单独运行swf文件才有效。具体代码为:
[code]fscommand("trapallkeys", true);
var keyListener:Object = new Object();
keyListener.onKeyDown = function() {
trace(Key.getCode());
if (Key.isDown(Key.CONTROL) && Key.getCode() == 67) {
txt.text = "ctrl+c";
}
};
Key.addListener(keyListener);[/code]

AS2:动态改变实例对象所属的类

七月 2nd, 2007 | No Comments , 178 views | Posted by flashlizi in Flash8/AS2

Object对象有2个属性:__proto__和prototype。__proto__是引用用于创建对象的类或构造函数的 prototype属性;prototype是对类或函数对象的超类的引用。在as2中,对象的基本继承都是通过原型链的。因此,我们可以利用Object对象的__proto__和prototype属性来实现动态改变实例对象所属的类。

类classA:
class classA
{
function classA ()
{
trace ("This is a instance of classA")
}
}

类classB:
class classB
{
function classB ()
{
trace ("This is a instance of classB")
}
}

接下来看实验代码:
import classA;
import classB;
var flashrek = new classA();
trace(flashrek instanceof classA);//true
var className = classB;
flashrek.__proto__ = className.prototype;
className.apply(flashrek, null);
trace(flashrek instanceof className);//true

AS2.0:利用Object.watch来控制函数执行队列

六月 22nd, 2007 | No Comments , 293 views | Posted by flashlizi in Flash8/AS2

很多时候,我们需要按照一定顺序执行一系列动作,必需保证一个动作完全执行完毕后再执行另外一个动作。解决办法很多,比如执行完一个动作就广播一个事件,再执行下一个动作。
现在我们利用Object.watch方法来实现这个目的(不熟悉相关方法的请看帮助),代码示例:
[code]var func = [func1, func2, func3];
var listener = {success:false};
listener.watch("success", callFunc);
var i = 0;
exec(0);
function exec(i) {
if (i < func.length) {
func[i]();
} else {
lietener.unwatch("success");
}
}
function callFunc(prop, oldVal, newVal) {
trace(prop + "{oldVal:" + oldVal + " newVal:" + newVal + "}");
if (newVal == true) {
i++;
exec(i);
}
return oldVal;
}
function func1() {
var id1 = setInterval(aa, 1000);
function aa() {
txt.text = "1:exec func1";
clearInterval(id1);
listener.success = true;
}
}
function func2() {
var id2 = setInterval(bb, 1000);
function bb() {
txt.text = "2:exec func2";
clearInterval(id2);
listener.success = true;
}
}
function func3() {
var id3 = setInterval(cc, 1000);
function cc() {
txt.text = "3:exec func3";
clearInterval(id3);
listener.success = true;
}
}[/code]
在此例中,实现了队列执行三个函数func1,func2,func3,每个函数的动作都是间隔1s后改变txt中的文本内容。恰好,我们利用了Object.watch方法来监控success属性,每当一个func[i]执行完毕后,就会改变success为true,继而执行下一个函数。此方法比和事件侦听是同一原理,但更为简洁实用。

解决Form中ExternalInterface的Bug问题

一月 20th, 2007 | No Comments , 234 views | Posted by flashlizi in Flash8/AS2

ExternalInterface API是专门处理flash与外部应用的交互的。在IE浏览器下,将flash对象放在form标签之间的时候,js就会报错,ExternalInterface的call和addcallback方法失效。网上有2种解决办法,经测试均有效。

1、加一个

在你嵌套flash的form里的

标记后面:
[code]<form><form></form>
//这里是你的flash代码内容。
</form>[/code]
这算是一个小hack吧。

2、添加如下JS在你的flash之前:
[code]<script type="text/javascript">
function ExternalInterfaceManager()
{
this.registerMovie = function(movieName) {
if(!window.fakeMovies) window.fakeMovies = new Array();
window.fakeMovies[window.fakeMovies.length] = movieName;
}
this.initialize = function() {
if(document.all)
{
if(window.fakeMovies)
{
for(i=0;i<window.fakeMovies.length;i++)
{
window[window.fakeMovies[i]] = new Object();
}
window.onload = initializeExternalInterface;
}
}

}
}
function initializeExternalInterface() {
for(i=0;i<window.fakeMovies.length;i++) {
var movieName = window.fakeMovies[i];
var fakeMovie = window[movieName];
var realMovie = document.getElementById(movieName);

for(var method in fakeMovie) {
realMovie[method] = function() {flashFunction = " + method.toString() + "\" returntype=\"javascript\">" + __flash__argumentsToXML(arguments, 0) + "";this.CallFunction(flashFunction);}
}

window[movieName] = realMovie;
}
}
var eim = new ExternalInterfaceManager();
eim.registerMovie("flash_id");
eim.initialize();
</script>[/code]
其中eim.registerMovie("flash_id"); 中的flash_id为你的swf的ID。

AS2类:颜色属性ColorProperty(饱和度对比度等)

一月 20th, 2007 | No Comments , 275 views | Posted by flashlizi in Flash8/AS2

用AS来调整图片的色相、亮度、灰度、饱和度、对比度、反相虽然不难,但因为涉及到ColorMatrixFilter的颜色矩阵的应用,使用起来有点麻烦,因此写了这个类ColorProperty。
这个类是对MovieClip类扩展,为MovieClip增加了这些属性:色相:_hue,亮度:_brightness,灰度:_grayscale,饱和度:_saturation,对比度:_contrast,反相:_invert。
当然,你也可以改写这个类,使之成为一个新类,而不是扩展MovieClip类。

用法(与_width,_height用法一样):
import ColorProperty;
ColorProperty.init();
//色相,取值范围为:-180~180
//img._hue=100;
//trace(img._hue);
//亮度,取值范围为:-255~255
img._brightness = 100;
//trace(img._brightness)
//灰度,布尔值,true为灰度,false则反之。
//img._grayscale = true;
//trace(img._grayscale);
//饱和度,一般范围为:0~3为宜
//img._saturation = 3;
//trace(img._saturation);
//对比度,取值范围为:0~1
//img._contrast = 0.15;
//反相,布尔值,true为反相,false则反之。
//trace(img._contrast);
//img._invert=true;

附上源文件和演示:点击下载ColorProperty

一组非常好的讲解Matrix应用的文章

一月 19th, 2007 | No Comments , 277 views | Posted by flashlizi in Flash8/AS2

矩阵转换在变形、颜色调整、滤镜等方面有非常重要的应用。下面是一组这方面非常好的英文教程:
1、利用Matrix在Flash中做几何变换,调整颜色和卷积特效http://www.adobe.com/devnet/flash/articles/matrix_transformations_print.html
2、理解Flash8中的矩阵变换
http://www.senocular.com/flash/tutorials/transformmatrix/
3、颜色矩阵类(ColorMatrix Class)http://www.gskinner.com/blog/archives/2005/09/flash_8_source.html
4、回旋矩阵(Convolution Matrix)
http://docs.gimp.org/en/plug-in-convmatrix.html