页游聊天模块图文混排解决方案
找了很长时间的聊天模块添加表情的解决方案。综合比较一下,最终选择闪刀浪子的TalkField。
选择它的理由:代码量小,简单易懂,使用方便。可以满足项目需求。
网上提供的其它几种方案,如果不能够熟知其原理,项目出什么问题了,维护起来时比较麻烦的。
预览:
主文档代码:
package { import flash.display.Loader; import flash.display.LoaderInfo; import flash.display.MovieClip; import flash.display.Sprite; import flash.events.Event; import flash.events.MouseEvent; import flash.events.TextEvent; import flash.net.URLRequest; import flash.system.ApplicationDomain; public class Main extends Sprite { private var _loader:Loader; private var _outputText:TalkField; private var _inputText:TalkField; private var _sendBtn:Button;//发送按钮 private var _faceBar:MovieClip; private var _app:ApplicationDomain; [Embed(source="face.swf",mimeType="application/octet-stream")] public var swfClass:Class; public function Main() { _loader = new Loader(); _loader.contentLoaderInfo.addEventListener(Event.COMPLETE,onComplete); //_loader.load(new URLRequest('face.swf')); _loader.loadBytes(new swfClass()); } private function onComplete(evt:Event):void { _app = (evt.currentTarget as LoaderInfo).applicationDomain; var _faceBarClass:Class = _app.getDefinition('faceBar') as Class; _faceBar = new _faceBarClass(); initText(); } private function initText():void { _outputText = new TalkField(300,200,_app); _outputText.tf.selectable = false; this.addChild(_outputText); _outputText.x = stage.stageWidth-_outputText.width >> 1; _outputText.y = 30; _outputText.tf.addEventListener(TextEvent.LINK,onLink); _inputText = new TalkField(300,26,_app,'input'); this.addChild(_inputText); _inputText.x = stage.stageWidth-_inputText.width >> 1; _inputText.y = 280; _inputText.setText('输入聊天信息'); _inputText.tf.restrict = '^/[\u3000]/g';//限制不许输入全角空格 this.addChild(_faceBar); _faceBar.x = 220; _faceBar.y = _inputText.y - 30; _faceBar.addEventListener(MouseEvent.CLICK,onBarClick); _sendBtn = new Button('发送'); this.addChild(_sendBtn); _sendBtn.x = _inputText.x + _inputText.width + 5; _sendBtn.y = _inputText.y; _sendBtn.addEventListener(MouseEvent.CLICK,sendMsg); } private function onBarClick(evt:MouseEvent):void { var str:String = evt.target.name.replace(/f/g,'/'); _inputText.tf.appendText(str); } private function onLink(evt:TextEvent):void { _inputText.setText(evt.text); } private var arr:Array = new Array(); private function sendMsg(event:MouseEvent):void { arr.push("/07<a href='event:这是我的姓名'><u>[鬼精灵]</u></a>说:" + _inputText.tf.text + '<br />'); _outputText.setMultiText(arr); _inputText.tf.text = ''; } } }
闪刀浪子开源类TalkField:
package { import flash.display.MovieClip; import flash.display.Sprite; import flash.events.Event; import flash.events.MouseEvent; import flash.filters.GlowFilter; import flash.geom.Rectangle; import flash.system.ApplicationDomain; import flash.text.TextField; import flash.text.TextFieldType; import flash.text.TextFormat; /** * 图文显示框 * @author 闪刀浪子 * 使用方法: */ public class TalkField extends Sprite { private var _tf:TextField; private var _type:String; private var _tfMask:Sprite; private var _faceContainer:Sprite; private var _maskWidth:Number; private var _maskHeight:Number; private var _textFormat:TextFormat; private var _leading:Number private var _textColor:uint; private var _appDomain:ApplicationDomain; /** * 构造函数 * @param width 图文宽度 * @param height 图文框高度 * @param leading 显示的文本行的行间距 * @param appDomain 包含"facexx"的程序域 * @param textColor 默认文本的颜色,如果没有用<font>标签定义颜色,则使用此颜色 * @param alpha 图文框的背景透明度 */ public function TalkField(width:Number, height:Number, appDomain:ApplicationDomain = null,textType:String = 'dynamic', leading:Number=2,textColor:uint=0xffffff) { trace(TextFieldType.DYNAMIC); _maskWidth = width; _maskHeight = height; _leading = leading; _textColor = textColor _type = textType; _appDomain = appDomain==null?ApplicationDomain.currentDomain:appDomain; initView() initEvent(); } private function initView():void { createBK(); createMask(); createTF(); createFaceContainer(); } private function initEvent():void { addEventListener(MouseEvent.MOUSE_WHEEL, onMouseWheelHandler); } private function onMouseWheelHandler(e:MouseEvent):void { maskY -= (e.delta * 4.0); dispatchEvent(new Event("scroll")); } private function createBK():void { graphics.beginFill(0, 0.3); graphics.drawRect( 0, 0, _maskWidth + 10, _maskHeight + 14); graphics.endFill(); } private function createMask():void { _tfMask = new Sprite(); _tfMask.graphics.beginFill(0x000000); _tfMask.graphics.drawRect(0, 0, _maskWidth, _maskHeight); _tfMask.graphics.endFill(); addChild(_tfMask); } private function createTF():void { _textFormat = new TextFormat; _textFormat.color=_textColor; _textFormat.size = 12; _textFormat.letterSpacing = 0.75; _textFormat.leading = _leading; _tf = new TextField(); _tf.textColor = 0xffffff; _tf.width = _maskWidth; _tf.defaultTextFormat = _textFormat; // _tf.selectable = false; _tf.multiline = true; _tf.wordWrap = true; _tf.autoSize = "left"; _tf.type = _type; _tf.filters = [new GlowFilter(0x000000, 0.95, 2, 2, 10)]; _tf.mouseWheelEnabled = false; addChild(_tf); _tf.mask = _tfMask; } private function createFaceContainer():void { _faceContainer = new Sprite(); _faceContainer.scrollRect = new Rectangle(0, 0, _maskWidth, _maskHeight); addChild(_faceContainer); } private function clearFaceContain():void { while (_faceContainer.numChildren > 0) { _faceContainer.removeChildAt(0); } } /** * 聊天显示框 * @param str 必须为htmlText格式 */ public function setText(str:String):void { _tf.text = ""; _tf.defaultTextFormat = _textFormat; var faceArr:Array = []; clearFaceContain(); //保存表情符的编号并替换为空格,此处可以根据你的表情数量来修改正则表达式 //表情素材的导出类名规则为——face01-face05 var face:Array = str.match(/\/(0[1-7])/g); if (face != null) { faceArr = faceArr.concat(face); } //注意这里是将表情编号替换为全角的空格,所以记住你的输入框要禁止玩家输入全角空格 //需要替换的内容是:*01 - *09 str = str.replace(/\/(0[1-7])/g, "<font size='24'> </font>"); _tf.htmlText = str; _tf.height; //记录空格的索引号 var text:String = _tf.text; var indexArr:Array = []; for (var index:int = 0; index < text.length; index++) { if (text.charAt(index) == " ") { indexArr.push(index); } } _tf.height; for (var j:uint = 0; j < indexArr.length; j++) { var tempPos:Rectangle = _tf.getCharBoundaries(indexArr[j]); var linkClass:Class = _appDomain.getDefinition("face" + faceArr[j].substr(1, 2)) as Class; if (linkClass != null&&tempPos!=null) { var mc:MovieClip = new linkClass as MovieClip; _faceContainer.addChild(mc); mc.x = tempPos.x; mc.y = tempPos.y+3; } } dispatchEvent(new Event(Event.CHANGE)); } /** * 设置文本 * @param arr 频道数组 */ public function setMultiText(arr:Array):void { if (arr == null) return; _tf.text = ""; _tf.defaultTextFormat = _textFormat; var faceArr:Array = []; clearFaceContain(); var allStr:String="" for (var i:uint = 0; i < arr.length; i++) { var str:String = arr[i]; var face:Array = str.match(/\/(0[1-7])/g); if (face != null) { faceArr = faceArr.concat(face); } str = str.replace(/\/(0[1-7])/g, "<font size='24'> </font>"); allStr += str; } _tf.htmlText = allStr; _tf.height; //记录空格的索引号 var text:String = _tf.text; var indexArr:Array = []; for (var index:int = 0; index < text.length; index++) { if (text.charAt(index) == " ") { indexArr.push(index); } } _tf.height; for (var j:uint = 0; j < indexArr.length; j++) { var tempPos:Rectangle = _tf.getCharBoundaries(indexArr[j]); var linkClass:Class = _appDomain.getDefinition("face" + faceArr[j].substr(1, 2)) as Class; if (linkClass != null&&tempPos!=null) { var mc:MovieClip = new linkClass as MovieClip; _faceContainer.addChild(mc); mc.x = tempPos.x; mc.y = tempPos.y+3; } } dispatchEvent(new Event(Event.CHANGE)); } /* INTERFACE game.ui.list.IScrollElement */ public function get maskX():Number { return _faceContainer.scrollRect.x; } public function set maskX(val:Number):void { var rec:Rectangle = _faceContainer.scrollRect; rec.x = val; _tf.x = -val; _faceContainer.scrollRect = rec; } public function get maskY():Number { return _faceContainer.scrollRect.y; } public function set maskY(val:Number):void { var rec:Rectangle = _faceContainer.scrollRect; if (val < 0) val = 0; else if (val > maxScroll) val = maxScroll; _tf.y = -val; rec.y = val; _faceContainer.scrollRect = rec; } public function get minScroll():Number { return 0; } public function get maxScroll():Number { if (_tf.height <= _tfMask.height) return 0; else return _tf.height - _tfMask.height; } public function get tf():TextField { return _tf; } } }