zoukankan      html  css  js  c++  java
  • BmpCacheMovieClip

    package LibCore.ui.core
    {
    	import LibCore.utils.ClassUtils;
    	import LibCore.utils.DisplayObjectUtils;
    	import LibCore.utils.NumberUtils;
    	
    	import flash.display.Bitmap;
    	import flash.display.FrameLabel;
    	import flash.display.MovieClip;
    	import flash.events.Event;
    	import flash.geom.Point;
    	import flash.utils.Dictionary;
    	
    	/**
    	 * 采用位图缓存处理的影片剪辑
    	 * <p>
    	 * <li>对于内容复杂(尤其是使用了很多滤镜)但固定的影片剪辑,非常耗CPU,而Flash自带的位图缓存机制又无法加以优化,因此采用手动方式实现</li>
    	 * <li>将原影片剪辑的每帧缓存为一张位图,并始终保存,实际使用时用位图代替原影片剪辑显示,且支持多个实例间共享</li>
    	 * </p>
    	 * @author	Fictiony
    	 * @version	2017/3/21
    	 */	
    	public class BmpCacheMovieClip extends MovieClip
    	{
    		static private var _bmpCacheMap:Dictionary = new Dictionary();	//位图缓存表:{原影片剪辑类或实例: [帧缓存信息]}
    		static private var _mcCacheMap:Dictionary = new Dictionary();	//影片剪辑实例缓存表:{原影片剪辑类: 影片剪辑实例}
    		static private var _tempOffset:Point = new Point();				//临时偏移坐标记录
    		
    		private var _sourceClass:Class;				//原影片剪辑类(null表示构造时指定的是实例)
    		private var _sourceMC:MovieClip;			//原影片剪辑实例
    		private var _content:Bitmap;				//内容位图(用于显示每帧的缓存位图)
    		private var _totalFrames:int = 0;			//总帧数
    		private var _currentFrame:int = 0;			//当前帧序号
    		private var _isPlaying:Boolean = false;		//是否正在播放
    		private var _labels:Array;					//原影片剪辑的所有帧标签列表(不考虑场景)
    		private var _labelMap:Dictionary;			//帧标签表:{帧标签: 帧序号}
    		private var _originSize:Point;				//指定的原始大小
    		
    		/**
    		 * 构造函数
    		 * @param sourceMC			原影片剪辑类或实例
    		 * @throws ArgumentError	若sourceMC不为影片剪辑类或实例,则抛出异常
    		 */		
    		public function BmpCacheMovieClip( sourceMC:Object )
    		{
    			super();
    			
    			if (sourceMC is MovieClip)
    			{
    				_sourceMC = sourceMC as MovieClip;
    			}
    			else if (sourceMC is Class && ClassUtils.extendsClass(sourceMC as Class, MovieClip))
    			{
    				_sourceClass = sourceMC as Class;
    			}
    			else
    			{
    				throw new ArgumentError("Parameter sourceMC should be a subclass or instance of MovieClip: " + sourceMC);
    			}
    			init();
    		}
    
    		/**
    		 * 总帧数
    		 */		
    		override public function get totalFrames():int
    		{
    			return _totalFrames;
    		}
    
    		/**
    		 * 当前帧序号
    		 */		
    		override public function get currentFrame():int
    		{
    			return _currentFrame;
    		}
    
    		/**
    		 * 当前是否正在播放
    		 */		
    		override public function get isPlaying():Boolean
    		{
    			return _isPlaying;
    		}
    		
    		/**
    		 * 所有帧标签列表
    		 */		
    		override public function get currentLabels():Array
    		{
    			return _labels;
    		}
    		
    		/**
    		 * 指定的原始大小(null表示不指定)
    		 */
    		public function get originSize():Point
    		{
    			return _originSize ? _originSize.clone() : null;
    		}
    		public function set originSize( val:Point ):void
    		{
    			_originSize = val ? new Point(Math.max(1, val.x || 0), Math.max(1, val.y || 0)) : null;
    		}
    		
    		/**
    		 * 宽度
    		 */
    		override public function get width():Number
    		{
    			return _originSize ? _originSize.x * this.scaleX : super.width;
    		}
    		override public function set width( val:Number ):void
    		{
    			if (_originSize)
    			{
    				this.scaleX = (val || 0) / this.originSize.x;
    			}
    			else
    			{
    				super.width = val;
    			}
    		}
    
    		/**
    		 * 高度
    		 */
    		override public function get height():Number
    		{
    			return _originSize ? _originSize.y * this.scaleY : super.height;
    		}
    		override public function set height( val:Number ):void
    		{
    			if (_originSize)
    			{
    				this.scaleY = (val || 0) / this.originSize.y;
    			}
    			else
    			{
    				super.height = val;
    			}
    		}
    		
    		/**
    		 * 初始化
    		 */		
    		private function init():void
    		{
    			if (_sourceClass)	//指定类
    			{
    				if (_sourceClass in _bmpCacheMap)
    				{
    					_sourceMC = _mcCacheMap[_sourceClass] as MovieClip;
    				}
    				else
    				{
    					_sourceMC = new _sourceClass();
    					_bmpCacheMap[_sourceClass] = new Vector.<FrameCacheInfo>(_sourceMC.totalFrames, true);
    					_mcCacheMap[_sourceClass] = _sourceMC;
    				}
    			}
    			else	//指定实例
    			{
    				if (!(_sourceMC in _bmpCacheMap))
    				{
    					_bmpCacheMap[_sourceMC] = new Vector.<FrameCacheInfo>(_sourceMC.totalFrames, true);
    				}
    			}
    			
    			//初始化影片剪辑参数
    			_totalFrames = _sourceMC.totalFrames;
    			_labels = _sourceMC.currentLabels;
    			if (_labels && _labels.length > 0)
    			{
    				_labelMap = new Dictionary();
    				for each (var label:FrameLabel in _labels)
    				{
    					_labelMap[label.name] = label.frame;
    				}
    			}
    
    			//创建内容,并显示第一帧
    			_content = new Bitmap();
    			_content.smoothing = true;
    			addChild(_content);
    			gotoFrame(1);
    		}
    		
    		/**
    		 * 开始播放
    		 */		
    		override public function play():void
    		{
    			if (_isPlaying || this.totalFrames < 2) return;
    			addEventListener(Event.ENTER_FRAME, onFrame);
    			_isPlaying = true;
    		}
    		
    		/**
    		 * 停止播放
    		 */		
    		override public function stop():void
    		{
    			if (!_isPlaying) return;
    			removeEventListener(Event.ENTER_FRAME, onFrame);
    			_isPlaying = false;
    		}
    		
    		/**
    		 * 跳转到指定帧并播放
    		 * @param frame		帧序号或帧标签
    		 */		
    		override public function gotoAndPlay( frame:Object, scene:String=null ):void
    		{
    			gotoFrame(frame);
    			play();
    		}
    		
    		/**
    		 * 跳转到指定帧并停止
    		 * @param frame		帧序号或帧标签
    		 */		
    		override public function gotoAndStop( frame:Object, scene:String=null ):void
    		{
    			gotoFrame(frame);
    			stop();
    		}
    
    		/**
    		 * 跳转到上一帧并停止
    		 */		
    		override public function prevFrame():void
    		{
    			gotoFrame(this.currentFrame > 1 ? this.currentFrame - 1 : this.totalFrames);
    			stop();
    		}
    		
    		/**
    		 * 跳转到下一帧并停止
    		 */		
    		override public function nextFrame():void
    		{
    			gotoFrame(this.currentFrame < this.totalFrames ? this.currentFrame + 1 : 1);
    			stop();
    		}
    		
    		/**
    		 * 跳转到指定帧
    		 * @param frame		帧序号或帧标签
    		 */
    		protected function gotoFrame( frame:* ):void
    		{
    			if (_labelMap && frame in _labelMap)
    			{
    				frame = _labelMap[frame];
    			}
    			frame = NumberUtils.limit(int(frame), 1, this.totalFrames);
    			if (frame == _currentFrame) return;
    			_currentFrame = frame;
    			
    			//若该帧缓存位图尚未创建,则先创建
    			var cache:Vector.<FrameCacheInfo> = _bmpCacheMap[_sourceClass || _sourceMC];
    			if (!cache) return;
    			var info:FrameCacheInfo = cache[_currentFrame - 1];
    			if (!info)
    			{
    				_sourceMC.gotoAndStop(_currentFrame);
    				info = new FrameCacheInfo();
    				info.bitmap = DisplayObjectUtils.drawToBitmap(_sourceMC, 0, _tempOffset);
    				info.offsetX = _tempOffset.x;
    				info.offsetY = _tempOffset.y;
    				cache[_currentFrame - 1] = info;
    			}
    
    			//刷新内容
    			_content.bitmapData = info.bitmap;
    			_content.x = info.offsetX;
    			_content.y = info.offsetY;
    		}
    		
    		/**
    		 * 每帧处理
    		 */		
    		private function onFrame( e:Event ):void
    		{
    			gotoFrame(this.currentFrame < this.totalFrames ? this.currentFrame + 1 : 1);
    		}
    		
    		/**
    		 * 清除位图缓存(清除后所有已存在的相关影片剪辑都将不再刷新内容,但新创建的不受影响)
    		 * @param sourceMC	原影片剪辑类或实例
    		 */
    		public function clearBmpCache():void
    		{
    			BmpCacheMovieClip.clearBmpCache(_bmpCacheMap);
    		}
    		static public function clearBmpCache( sourceMC:Object ):void
    		{
    			var cache:Vector.<FrameCacheInfo> = _bmpCacheMap[sourceMC];
    			if (cache)
    			{
    				for each (var info:FrameCacheInfo in cache)
    				{
    					info.bitmap.dispose();
    				}
    				delete _bmpCacheMap[sourceMC];
    				delete _mcCacheMap[sourceMC];
    			}
    		}
    	}
    }
    
    import flash.display.BitmapData;
    
    /**
     * 帧缓存信息
     */
    class FrameCacheInfo
    {
    	public var bitmap:BitmapData;	//该帧的缓存位图
    	public var offsetX:int;			//偏移X坐标
    	public var offsetY:int;			//偏移Y坐标
    }
    

      

  • 相关阅读:
    vsftpd用户登陆目录
    Linux下能否用用apache运行ASP.NET的WebService
    rose软件下载(Rational Rose 2003 Enterprise Edition)
    linux删除目录
    2013314 生活日记
    ubuntu12.10安装GTK+
    SqlServer 基础知识数据检索、查询排序
    获取时间段:本周、本月、本年
    二、自定义控件之RadioButtonList
    ext.net 开发学习之FileUploadField与Image (四)
  • 原文地址:https://www.cnblogs.com/dt1991/p/14841286.html
Copyright © 2011-2022 走看看