首页 > AS, myLib > ProgressiveLoader 渐进式加载图像

ProgressiveLoader 渐进式加载图像

2009年12月10日 发表评论 阅读评论

新版本:http://www.lite3.cn/blog/?p=784


渐进式加载类,用法跟Loader差不多.

不同点:

  1. 当加载流错误时只能获取到 "Error #2124: 加载的文件为未知类型。"
  2. 侦听contentLoaderInfo的Progress事件的bytesLoaded,bytesTotal是整个文件的已加载字节和总字节.
  3. contentLoaderInfo.bytesLoaded, contentLoaderInfo.bytesTotal指当前loader里的字节数和总字节.

ProgressiveLoader

package cn.lite3.net 
{
	import flash.display.LoaderInfo;
	import flash.errors.IOError;
	import flash.events.Event;
	import flash.events.IOErrorEvent;
	import flash.events.ProgressEvent;
	import flash.events.SecurityErrorEvent;
	import flash.system.LoaderContext;
	import flash.display.Loader;
	import flash.net.URLRequest;
	import flash.net.URLStream;
	import flash.utils.ByteArray;
 
	/**
	 * 渐进式加载类
	 * 用法跟Loader一样,
	 * <p><b>不同点:</b></p>
	 * 1.当加载流错误时只能获取到 "Error #2124: 加载的文件为未知类型。" <br/>
	 * 2.侦听contentLoaderInfo的Progress事件的bytesLoaded,bytesTotal是整个文件的已加载字节和总字节.<br/>
	 * 3.contentLoaderInfo.bytesLoaded, contentLoaderInfo.bytesTotal指当前loader里的字节数和总字节
	 * 
	 * @author lite3
	 */
	public class ProgressiveLoader extends Loader
	{
		private var bytesLoaded:uint = 0;			// 已加载的字节数
		private var bytesToal:uint = 0; 			// 总字节数
 
		private var dataChange:Boolean = false;		// buffer的数据是否改变	
		private var streamComplete:Boolean = false;	// 文件是否加载完成
 
		private var context:LoaderContext;			// 
 
		private var buffer:ByteArray;				// 数据缓存
		private var stream:URLStream;				// 流
 
		/**
		 * 关闭流,并清理所有侦听器
		 */
		override public function close():void 
		{
			// 清除流相关
			if (stream)
			{
				if (stream.connected) stream.close();
				streamRemoveEvent(stream);
			}
			// 清除conentLoaderInfo相关的事件
			if (contentLoaderInfo.hasEventListener(Event.COMPLETE))
			{
				loaderInfoRemoveEvent(super.contentLoaderInfo);
			}
			// 清除显示数据事件
			if (hasEventListener(Event.ENTER_FRAME))
			{
				removeEventListener(Event.ENTER_FRAME, showData);
			}
			buffer = null;
		}
		/**
		 * 加载字节数据,不会在内部触发contentLoaderInfo相关事件
		 * @param	bytes
		 * @param	context
		 */
		override public function loadBytes(bytes:ByteArray, context:LoaderContext = null):void
		{
			close();
			super.unload();
			super.loadBytes(bytes, context);
		}
 
		/**
		 * 加载一个url文件,并渐进显示(如果是渐进格式)
		 * @param	request
		 * @param	context
		 */
		override public function load(request:URLRequest, context:LoaderContext = null):void 
		{
			streamComplete = false;
			if (!stream) stream = new URLStream();
			if (stream.connected) stream.close();
			this.context = context;
			dataChange = false;
 
			buffer = new ByteArray();
			super.unload();
			addEventListener(Event.ENTER_FRAME, showData);
			loaderInfoAddEvent(super.contentLoaderInfo);
			streamAddEvent(stream);
			stream.load(request);
		}
 
		// 将缓存中的数据显示为图像
		private function showData(e:Event = null):void 
		{
			if (!dataChange || !stream.connected) return;
 
			dataChange = false;
			if (stream.bytesAvailable > 0)
			{
				stream.readBytes(buffer, buffer.length, stream.bytesAvailable);
			}
			if (buffer.length > 0)
			{
				super.unload();
				super.loadBytes(buffer, context);
			}
 
			// 加载完成
			if (streamComplete)
			{
				close();
				streamComplete  = false;
			}
		}
		// 修正contentLoaderInfo的ProgressEvent.PROGRESS事件的进度值
		private function loaderProgressHandler(e:ProgressEvent):void 
		{
			e.bytesLoaded = bytesLoaded;
			e.bytesTotal = bytesToal;
		}
 
		// 显示完成
		private function loaderCompleteHandler(e:Event):void 
		{
			if (streamComplete)
			{
				streamComplete = false;
				loaderInfoRemoveEvent(super.contentLoaderInfo);
			}else
			{
				e.stopImmediatePropagation();
			}
		}
 
		// 数据加载完成
		private function streamCompleteHandler(e:Event):void 
		{
			streamRemoveEvent(stream);
			// 这里不删除EnterFrame事件,最后一段总是不会显示,
			// 并且complete事件里showData也不行,
			// 所以最后延时显示一次,
			streamComplete = true;
			dataChange = true;
		}
		// 数据加载中,保存数据加载的值
		private function streamProgressHandler(e:ProgressEvent):void 
		{
			bytesLoaded = e.bytesLoaded;
			bytesToal = e.bytesTotal;
			dataChange = true;
		}
		// 数据流错误, 但是也会加载400K左右的数据,
		// 然后由contentLoaderInfo抛出IOError或者IOErrorEvent
		// 但不会是流错误,而是未知文件类型
		private function streamErrorHandler(e:IOError):void 
		{
			close();
		}
 
		private function streamAddEvent(stream:URLStream):void
		{
			stream.addEventListener(Event.COMPLETE, streamCompleteHandler);
			stream.addEventListener(ProgressEvent.PROGRESS, streamProgressHandler);
			stream.addEventListener(IOErrorEvent.IO_ERROR, streamErrorHandler);
		}
 
		private function streamRemoveEvent(stream:URLStream):void
		{
			stream.removeEventListener(Event.COMPLETE, streamCompleteHandler);
			stream.removeEventListener(ProgressEvent.PROGRESS, streamProgressHandler);
			stream.removeEventListener(IOErrorEvent.IO_ERROR, streamErrorHandler);
		}
 
		private function loaderInfoAddEvent(loaderInfo:LoaderInfo):void
		{
			loaderInfo.addEventListener(Event.COMPLETE, loaderCompleteHandler, false, int.MAX_VALUE);
			loaderInfo.addEventListener(ProgressEvent.PROGRESS, loaderProgressHandler, false, int.MAX_VALUE);
		}
 
		private function loaderInfoRemoveEvent(loaderInfo:LoaderInfo):void
		{
			loaderInfo.removeEventListener(Event.COMPLETE, loaderCompleteHandler);
			loaderInfo.removeEventListener(ProgressEvent.PROGRESS, loaderProgressHandler);
		}
	}
}

这里是旧版本,不提供下载了.

分类: AS, myLib 标签: ,
  1. 2010年1月9日23:30 | #1

    写得不错,我的文章中有引用博主的内容
    http://www.catfly.cn/2009/12/catflash/593.html

  2. 2010年1月9日23:38 | #2

    @catfly
    没事,有这里的链接就OK了,呵呵,写来就是让大家看的,呵呵 :razz:

  3. 2010年7月20日13:54 | #3

    示例看不到了

  4. 2010年7月20日14:29 | #4

    @风
    可以看到的啊,可能的网络慢,刷新下看看 :razz:

  5. 2010年8月4日01:02 | #5

    会出现重复加载的现象!

  6. 2010年8月4日10:00 | #6

    @kyomic
    怎么出现的 :?: 我是用stream加载的图片资源,并且只加载一次的

  7. 2010年8月5日01:53 | #7

    @kyomic
    你指的重复加载是不是说的闪烁的情况啊
    http://www.lite3.cn/blog/?p=784 这里是修复了闪烁的版本 :grin:

  8. 2010年8月10日19:31 | #8

    高,你知道怎么要去除加载过程中的灰色背景么(图片背景)

  9. 2010年8月10日21:44 | #9

    @kyomic
    这个不太清楚的 :roll:

  1. 2010年1月12日23:47 | #1
  2. 2010年8月6日10:43 | #2
有话直说(用户名,邮箱只需填写一次,然后保存到cookie里,第二次将不必重新填写)