AS3聊天多行输入框图文混排完美实现

此处是私聊面板多行输入框的图文混排实现,类似于QQ聊天面板。

想要单行的输入框图文混排,请点击这里传送:

AS3聊天输入框图文混排完美实现

本文代码在上一篇文章中的代码简单修改而来,所以就不做注释了。

所有的注释都在上一篇文章的代码里,请自行移步。

package
{
	import flash.display.MovieClip;
	import flash.display.Shape;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.KeyboardEvent;
	import flash.filters.GlowFilter;
	import flash.geom.Rectangle;
	import flash.text.TextField;
	import flash.text.TextFieldType;
	import flash.text.TextFormat;
	import flash.text.TextFormatAlign;
	import flash.ui.Keyboard;
	import flash.utils.getDefinitionByName;
	
	public class InputText extends Sprite
	{
		private const PLACEHOLDER:String = String.fromCharCode(12288);
		
		public var textField:TextField;
		private var mcLayer:Sprite;
		private var dataList:Vector.<Express>;
		
		private var begin:int = 0;
		private var end:int = 0;
		private var scrollV:int = 0;
		private var keyCode:uint = 0;
		
		private var defaultFormat:TextFormat;
		private var placeFormat:TextFormat;
		
		public function InputText(w:Number = 400, h:Number = 200)
		{
			defaultFormat = new TextFormat();
			defaultFormat.color = 0xFFFFFF;
			defaultFormat.size = 12;
			defaultFormat.leading = 10;
			defaultFormat.letterSpacing = 0;
			defaultFormat.align = TextFormatAlign.LEFT;
			defaultFormat.font = "SimSun";
			
			placeFormat = new TextFormat();
			placeFormat.letterSpacing = 16;
			
			textField = new TextField();
			textField.width = w;
			textField.height = h;
			textField.type = TextFieldType.INPUT;
			textField.defaultTextFormat = defaultFormat;
			textField.multiline = true;
			textField.wordWrap = true;
			textField.mouseWheelEnabled = false;
			textField.restrict = "^" + PLACEHOLDER;
			textField.filters = [new GlowFilter(0x0, 1, 3, 3, 3)];
			textField.maxChars = 200;
			textField.addEventListener(Event.SCROLL, onTextScroll);
			textField.addEventListener(Event.CHANGE, afterChange);
			textField.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown);
			this.addChild(textField);
			
			var mask:Shape = new Shape();
			mask.graphics.beginFill(0);
			mask.graphics.drawRect(0, 0, w, h);
			mask.graphics.endFill();
			this.addChild(mask);
			
			mcLayer = new Sprite();
			mcLayer.mask = mask;
			this.addChild(mcLayer);
			dataList = new Vector.<Express>();
		}
		
		private function onTextScroll(e:Event):void
		{
			if(textField.scrollV != scrollV)
			{
				scrollV = textField.scrollV;
				layout();
			}
		}
		
		private function onKeyDown(e:KeyboardEvent):void
		{
			begin = textField.selectionBeginIndex;
			end = textField.selectionEndIndex;
			keyCode = e.keyCode;
		}
		
		private function afterChange(e:Event = null):void
		{
			var $begin:int = begin;
			if(begin == end)
			{
				if(keyCode == Keyboard.BACKSPACE)
				{
					delExpress(begin - 1);
					$begin = (begin > 0) ? begin - 1 : 0;
				}
				else if(keyCode == Keyboard.DELETE)
				{
					delExpress(begin);
				}
			}
			else
			{
				for(var i:int = begin; i < end; i++)
				{
					delExpress(i);
				}
			}
			updateExpressIndex($begin);
			layout();
			keyCode = 0;
		}
		
		private function layout():void
		{
			if(textField.length == 0)
			{
				clear();
				return;
			}
			textField.setTextFormat(defaultFormat, 0, textField.length);
			var textStr:String = textField.text;
			for(var i:int = 0; i < textStr.length; i++)
			{
				var char:String = textStr.charAt(i);
				if(char == PLACEHOLDER)
				{
					textField.setTextFormat(placeFormat, i, i + 1);
				}
			}
			while(mcLayer.numChildren > 0)
			{
				mcLayer.removeChildAt(0);
			}
			for each(var data:Express in dataList)
			{
				var rect:Rectangle = textField.getCharBoundaries(data.index);
				if(rect != null)
				{
					data.mc.x = rect.x + 2;
					data.mc.y = rect.y - 6;
					mcLayer.addChild(data.mc);
				}
			}
		}
		
		public function insertExpression(sign:String):void
		{
			if(textField.length >= textField.maxChars)
			{
				return;
			}
			begin = textField.selectionBeginIndex;
			end = textField.selectionEndIndex;
			for(var i:int = begin; i < end; i++)
			{
				delExpress(i);
			}
			textField.replaceText(begin, end, PLACEHOLDER);
			
			var $i:int = -1;
			for(i = 0; i < dataList.length; i++)
			{
				var data:Express = dataList[i];
				if(data.index >= begin)
				{
					$i = i;
					break;
				}
			}
			var mc:MovieClip = getMovieClip(sign);
			if($i == -1)
			{
				dataList.push(new Express(begin, sign, mc));
			}
			else
			{
				dataList.splice($i, 0, new Express(begin, sign, mc));
			}
			
			updateExpressIndex(begin);
			layout();
			textField.setSelection(begin + 1, begin + 1);
		}
		
		private function updateExpressIndex($begin:int):void
		{
			var $i:int = -1;
			for(var i:int = 0; i < dataList.length; i++)
			{
				if(dataList[i].index >= $begin)
				{
					$i = i;
					break;
				}
			}
			if($i != -1)
			{
				var textStr:String = textField.text;
				for(i = $begin; i < textStr.length; i++)
				{
					if(textStr.charAt(i) == PLACEHOLDER)
					{
						dataList[$i++].index = i;
					}
				}
			}
		}
		
		private function getExpress(index:int):Express
		{
			for each(var data:Express in dataList)
			{
				if(data.index == index)
				{
					return data;
				}
			}
			return null;
		}
		
		private function delExpress(index:int):void
		{
			for(var i:int = 0; i < dataList.length; i++)
			{
				var data:Express = dataList[i];
				if(data.index == index)
				{
					dataList.splice(i, 1);
					if(mcLayer.contains(data.mc))
					{
						mcLayer.removeChild(data.mc);
					}
					return;
				}
			}
		}
		
		private function getMovieClip(sign:String):MovieClip
		{
			var $_class:Class = getDefinitionByName(sign) as Class;
			var $_item:MovieClip = new $_class();
			$_item.mouseChildren = false;
			$_item.mouseEnabled = false;
			return $_item;
		}
		
		public function get srcContent():String
		{
			var charArr:Array = [];
			var textStr:String = textField.text;
			for(var i:int = 0; i < textStr.length; i++)
			{
				var char:String = textStr.charAt(i);
				if(char == PLACEHOLDER)
				{
					var data:Express = getExpress(i);
					charArr.push(data.sign);
				}
				else
				{
					charArr.push(char);
				}
			}
			return charArr.join("");
		}
		
		public function set srcContent(content:String):void
		{
			clear();
			var reg:RegExp = new RegExp("chat_expression_[0-9]{2}", "igm");
			var signArr:Array = content.match(reg);
			content = content.replace(reg, PLACEHOLDER);
			if(content.length > textField.maxChars)
			{
				content = content.substr(0, textField.maxChars);
			}
			for(var i:int = 0; i < content.length; i++)
			{
				var char:String = content.charAt(i);
				if(char == PLACEHOLDER)
				{
					var sign:String = signArr.shift() as String;
					var mc:MovieClip = getMovieClip(sign);
					dataList.push(new Express(i, sign, mc));
				}
			}
			textField.text = content;
			layout();
		}
		
		public function clear():void
		{
			textField.htmlText = "";
			begin = end = scrollV = keyCode = 0;
			dataList = new Vector.<Express>();
			if(mcLayer != null)
			{
				while(mcLayer.numChildren > 0)
				{
					mcLayer.removeChildAt(0);
				}
			}
		}
	
	}
}
/*===============================================*/

import flash.display.MovieClip;

class Express
{
	public var index:int;
	public var sign:String;
	public var mc:MovieClip;
	
	public function Express(index:int, sign:String, mc:MovieClip)
	{
		this.index = index;
		this.sign = sign;
		this.mc = mc;
	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值