omiga

简单就好

LSO/Flash Cookie

4条评论»

SharedObject类创建的本地共享对象(LSO:local shared object)类似于浏览器cookie,所以也被称作Flash Cookie。类似只是在作用上类似,都是用于将数据保存于客户端,可进行读写。

不同之处似乎更多:

  • 浏览器cookie具有过期时间,而Flash Cookie默认永不过期,尽管可以间接地实现expires
  • 浏览器cookie文件大小不能超过4k,且同一域最多只能保存20个cookie,而Flash Cookie默认大小为100k,如若不够还可以向用户请求获取更多空间存储Flash Cookie
  • 浏览器cookie保存的数据都以字符串形式保存,而Flash Cookie可保存除了AS中可视对象和SharedObject对象本身的任何数据类型
  • 浏览器cookie无法跨浏览器进行读写,而Flash Cookie却是跨浏览器的,任何浏览器访问的Flash Cookie都可以是同一个.sol文件
  • 浏览器cookie最初为服务器端编程而设计,而且作为HTTP协议的扩展可以自动地在web浏览器与服务器之间传递,而Flash Cookie默认不会在浏览器与服务器之间进行传递
  • 浏览器cookie默认域为创建cookie页面所在域,而Flash Cookie默认域为创建Flash Cookie的swf文件所在域,未必是当前页面所在域

静态getLocal()方法是LSO创建和打开以进行读取的机制。getLocal()方法会返回ShareObject实例,用以取代new运算符以实例化新LSO实例。调用getLocal()方法时至少需要为其传入一个参数,即是LSO的名称;第二个参数是为LSO指定存储路径便于其他swf共享该LSO数据,默认保存路径为创建LSO的swf文件所在唯一域、路径和文件名组成;第三个参数用以确定对此共享对象的访问是否只限于通过HTTPS连接传递的swf文件,默认false。如:var user:SharedObject = SharedObject.getLocal(‘user’,'/’);

LSO通过其一个特殊的内建属性data来存储所有数据,如:user.data.name = ‘xxxx’;

在Flash Player卸载时、SharedObject实例被当成垃圾回收时、当调用SharedObject.clear()方法时,LSO数据都会自动保存至本地磁盘。但是这些方法都不值得信赖,推荐的方式是使用SharedObject.flush()方法来对LSO数据进行存储。flush()方法有一个可选参数,指定写入数据时应该使用的最小磁盘空间量,默认值为0,表示只使用所需的最小空间。

调用flush()方法返回以下三种结果:

  1. Error 用户拒绝保存该域的LSO数据,或者Flash Player由于某种原因不能保存数据都会抛出Error
  2. SharedObjectFlushStatus.FLUSHED 数据成功保存
  3. SharedObjectFlushStatus.PENDING 没有分配足够的磁盘空间来保存LSO数据。

LSO数据的读取与写入一样简单,只需将共享对象的data属性内的对应属性读取出来即可,如:var name:String = user.data.name;

而删除LSO对象中的数据则需要使用delete运算符,如:delete user.data.name;如需要删除整个LSO对象,调用clear()方法即可:user.clear();

以下代码定义了三个函数setCookie、getCookie、delCookie用以创建/修改、获取、删除LSO数据:

//LSO/FlashCookie wondger@gmail.com
import flash.events.NetStatusEvent;
function setCookie(lsoname:String,cname:String,cvalue:*,path:String=null):Boolean{
	var lso:SharedObject = (path!=null&&path.length) ? SharedObject.getLocal(lsoname,path) : SharedObject.getLocal(lsoname);
	lso.data[cname] = cvalue;
	try{
		var flushResult:String = lso.flush();
		if(flushResult == SharedObjectFlushStatus.FLUSHED) return true; //数据保存成功
		else if(flushResult == SharedObjectFlushStatus.PENDING) lso.addEventListener(NetStatusEvent.NET_STATUS,onStatus); //空间不够时
	}catch(e:Error){
		Security.showSettings(SecurityPanel.LOCAL_STORAGE); //用户禁止保存数据,打开Player的“settings”对话框
	}
	function onStatus(evt:NetStatusEvent):Boolean{
		lso.removeEventListener(NetStatusEvent.NET_STATUS,onStatus);
		if(evt.info.code == 'SharedObject.Flush.Success') return setCookie(lsoname,cname,cvalue); //用户同意允许请求更多的空间
		return false;
	}
	return false;
}
function getCookie(lsoname:String,cname:String,path:String=null):*{
	var lso:SharedObject = (path!=null&&path.length) ? SharedObject.getLocal(lsoname,path) : SharedObject.getLocal(lsoname);
	return lso.data[cname];
}
function delCookie(lsoname:String,cname:String=null,path:String=null):Boolean{
	var lso:SharedObject = (path!=null&&path.length) ? SharedObject.getLocal(lsoname,path) : SharedObject.getLocal(lsoname);
	if(lso){
		if(cname && cname != null){
			delete lso.data[cname];
			lso.flush();
		}else lso.clear();
		return true;
	}
	return false;
}

当然还可以使用JavaScript进行一定的封装方便跨浏览器操作(对检测flash加载完成addCallback注册函数可用一直纠结了很久,没有找到太满意的方法,现在这个将就用):demo

———————————————

update 2011/7/27

补充下,上面提到的间接地实现expires

文章写了很久也忘记了,我想可以这样,每次写cookie的时候,将expires作为一个数据字段保存,即user.data.expires = ****,每次读取cookie的时候,都将此expires读取出来与当前时间比较即可。

AS3绘制扇形

3条评论»

AS3中本身并没有提供绘制扇形的的方法,但是可以利用curveTo()来间接的完成这一任务。curveTo()绘制的曲线是接近Bezier曲线的曲线,并不是标准的圆弧,所以如果对精确度要求过高并不合适。

为了写这个类,努力地去回忆了下高中几何知识,再借助万能的Google才拼出了下面这张图(相信你一看就懂),看大图

看看demo~

Sector.as 源码(提供了一个reDraw方法,重新传递半径、起始角度和角度clear后重新绘制):

import flash.display.Sprite;
//Description:draw a sector by curveTo()
//Email:wondger[at]gmail.com
//Blog:http://omiga.org/
//Date:2010-08
public class Sector extends Sprite{
  private var _x0:Number; //圆心横坐标
  private var _y0:Number; //圆心纵坐标
  private var _r:Number; //圆半径
  private var _a0:Number; //起始角度 0度开始顺时针方向
  private var _lineWidth:Number; //线条宽度
  private var _lineColor:Number; //线条颜色
  private var _fillColor:Number; //填充颜色
  public function Sector(x0:Number,y0:Number,r:Number,a0:Number,a:Number,lineWidth:Number=1,lineColor:Number=0xFF0000,fillColor:Number=0xFFFF00){
    _x0 = x0;
    _y0 = y0;
    _r = r;
    _a0 = a0*Math.PI/180;
    _lineWidth = lineWidth;
    _lineColor = lineColor;
    _fillColor = fillColor;
    if(a>0&&a<=360) drawSector(a);
  }
  private function drawSector(a:Number):void{
    this.graphics.lineStyle(_lineWidth,_lineColor);
    this.graphics.beginFill(_fillColor);
    this.graphics.moveTo(_x0,_y0);
    this.graphics.lineTo(_x0+_r*Math.cos(_a0),_y0+_r*Math.sin(_a0)); //曲线绘制起始点
    var n:uint = Math.floor(a/45); //分段绘制接近Bezier曲线的曲线,分段越细,曲线越接近真实圆弧线
    var a0:Number = _a0; //记录初始角度
    while(n-->0){
      a0+=Math.PI/4;
      this.graphics.curveTo(_x0+_r/Math.cos(Math.PI/8)*Math.cos(a0-Math.PI/8),_y0+_r/Math.cos(Math.PI/8)*Math.sin(a0-Math.PI/8),_x0+_r*Math.cos(a0),_y0+_r*Math.sin(a0));
    }
    if(a%45){
      var am:Number = a%45*Math.PI/180;
      this.graphics.curveTo(_x0+_r/Math.cos(am/2)*Math.cos(a0+am/2),_y0+_r/Math.cos(am/2)*Math.sin(a0+am/2),_x0+_r*Math.cos(a0+am),_y0+_r*Math.sin(a0+am));
    }
    this.graphics.lineTo(_x0,_y0);
    this.graphics.endFill();
  }
  public function reDraw(r:Number,a0:Number,a:Number):void{
    if(a>0&&a<=360){
      _r = r;
      _a0 = a0*Math.PI/180;
      this.graphics.clear();
      drawSector(a);
    }
  }
}

Adobe Flash Player—Debugger Versions

2条评论»

ExternalInterface

发表评论»

ExternalInterface是一个外部的用于实现Actionscript和Flash Player容器之间通信的应用程序接口(诸如AS与JS的通信)。推荐对所有 JavaScript 与 ActionScript 之间的通信使用 ExternalInterface,替代较旧的fscommand(),getURL()方法。

ExternalInterface类有两个公共属性:

  1. available : Boolean [static][read-only] 指示此播放器是否位于提供外部接口的容器中。
  2. objectID : String [static][read-only] 在 Internet Explorer 中,返回标签的 id 属性;在 Netscape 中,返回 name 属性。

同时具有两个公共方法:

  1. addCallback(functionName:String, closure:Function):void [static] 将 ActionScript 方法注册为可从容器调用。
  2. call(functionName:String, … arguments):* [static] 调用由 Flash Player 容器公开的函数,不传递参数或传递多个参数。

ActionScript调用JavaScript demo

AS:

import flash.events.MouseEvent;
import flash.external.ExternalInterface;
bt.addEventListener(MouseEvent.MOUSE_UP,alert);
function alert(e:MouseEvent):void{
 ExternalInterface.call("alert","a demo for call \n http://omiga.org");
}

直接调用即可,当然,最好检查一下当前容器是否支持外部接口通信。

bt.addEventListener(MouseEvent.MOUSE_UP,alert);
function alert(e:MouseEvent):void{
 if(ExternalInterface.available){
 ExternalInterface.call("alert","a demo for call \n http://omiga.org");
 }
}

JavaScript调用ActionScript demo

AS:

import flash.external.ExternalInterface;
function setText(s){
 i_txt.text = s;
}
ExternalInterface.addCallback("setText",setText);

HTML:

<object id="mySWF"  classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,28,0" width="300" height="22">
 <param name="movie" value="addCallback.swf" />
 <param name="quality" value="high" />
 <param name="allowScriptAccess" value="always" />
 <embed src="addCallback.swf" quality="high" pluginspage="http://www.adobe.com/shockwave/download/download.cgi?P1_Prod_Version=ShockwaveFlash" type="application/x-shockwave-flash" width="300" height="22"></embed>
</object>
<button onclick="set()">设 置</button>
<script type="text/javascript">
function getFlash(id){
 if(document.all) return document.getElementById(id);
 else return document.getElementById(id).getElementsByTagName("embed")[0];
}
function set(){
 var s = prompt('请输入:');
 getFlash("mySWF").setText(s);
}
</script>