zoukankan      html  css  js  c++  java
  • AS3基于TextField实现图文并排更新于2015.08.05

      几年前写了个在文本中插入图像显示 类,当时比较懒,没有任何说明和Demo,代码中一些用到的类也没提供,只是单纯地想记录下如何解决,以至于直接复制代码保存。所以之前的代码也是无法直接拿去用。

      现在由于需要,刚开始找不到之前的代码,只能复制文章中的代码,发现改起来还挺费劲的,还好后来找到了完整的代码。坑了别人也把自己给坑了。

      现在我把坑填上,还是先贴核心类的代码,代码中写了些注释虽然可能不是很详细。另外附上项目文件,项目中包含需要用到的其它类和简单的使用Demo,下载地址:http://pan.baidu.com/s/1nt8ClN7

    package
    {
        import flash.display.Bitmap;
    
        public class ImgObject
        {
            public var src:String;
            public var id:String;
            public var imgWidth:Number;
            public var imgHeight:Number;
            public var imgXml:XML;
            public var image:Bitmap;
            public var index:int; //图像所在文本中的位置
            
            public function ImgObject()
            {
                
            }
        }
    }
    package
    {
        import flash.display.Bitmap;
        import flash.display.DisplayObject;
        import flash.display.Loader;
        import flash.display.Sprite;
        import flash.display.StageScaleMode;
        import flash.events.Event;
        import flash.events.IOErrorEvent;
        import flash.geom.Rectangle;
        import flash.net.URLRequest;
        import flash.text.AntiAliasType;
        import flash.text.TextField;
        import flash.text.TextFieldAutoSize;
        import flash.text.TextFieldType;
        import flash.text.TextFormat;
        import flash.text.TextLineMetrics;

        /**
         * 文本容器类
         * 该类主要处理在文本中包含显示图像,使文本与图像支持混合排列
         * 只支持显示,不支持编辑
         * 显示图像的格式为<img id='' width='20' height='20' src='图像地址'/>
         * 如:
         * var text:String = "这个一个图文混排的容器类<img width='20',height='20' src='/data/index.jpg'/>
         * var tc:TextContainer = new TextContainer(200,new TextFormat("微软雅黑"));
         * tc.setText(text);
         *
         * 如文本是HTMLText时:
         * var text:String = <P><FONT COLOR='#979797' >这个一个图文混排的容器类</FONT><img width='20',height='20' src='/data/index.jpg'/><br/><FONT COLOR='#babec2' >支持HTML格式文本</FONT><P>
         * var tc:TextContainer = new TextContainer(200);
         * tc.setHtmlText(text);
         *
         * 如果要获取TextContainer的高度,需要等处理显示完成后才能更新到正确的宽高,所以需要监听SETTEXTCOMPLETED事件
         * tc.addEventListener(TextContainer.SETTEXTCOMPLE,onSetTextCompleted,false,0,false);
         * function onSetTextCompleted(e:Event):void{
         *         var w:Number = tc.width;
         *         var h:Number = tc.height;
         *         updateSize();
         * }
         *
         */
        public class TextContainer extends Sprite
        {
            private var _textFormat:TextFormat; //文本格式
            private var _maxWidth:Number;       //容器的宽
            private var textStr:String;
            private var imgObjectArr:Array=new Array();
            private var textArr:Array=new Array();
            
            private var tempTf:TextField;
            
            private var _placeholder:String;
            private var _placeholderColor:uint;
            private var _placeholderMarginH:int;    
            private var _placeholderMarginV:int;
            private var _formatCalculator:TextField;
            
            private var loader:Loader;


            private var loadImgComplete:Function;
            private var loadIoError:Function;
            private var textLineHeight:Number;
            private var originalText:String;
            public static const SETTEXTCOMPLETED:String="SetTextCompleted";
            private const margins:int=5;
            private var _Number;
            private var _height:Number;
            private var isHtml:Boolean = false;
            
            private static var DEFAULT_FONT:String = "微软雅黑,Microsoft YaHei";
            
            /**
             *
             * @param maxWidth 文本容器最大宽度
             * @param format 默认文本
             *
             */
            public function TextContainer(maxWidth:Number=100,format:TextFormat=null)
            {
                this.mouseEnabled = this.mouseChildren = false;
                _textFormat=format;
        
                if(format!=null){
                    _textFormat=format;
                }else{
                    _textFormat=new TextFormat();
                    _textFormat.font=DEFAULT_FONT;
                }
            
                _maxWidth = maxWidth;
                
                _placeholder="&nbsp;";
                _placeholder=StringUtil.DecodingAscIIStr(_placeholder);
                _placeholderColor = 0x000000;
                _placeholderMarginH = 1;
                _placeholderMarginV = 0;
                _formatCalculator = new TextField();            
                _formatCalculator.text = _placeholder;
                textLineHeight=Number(_textFormat.size);
                
            }
            
            /**
             * 设置HTML格式的文本
             * @param htmlText
             *
             */
            public function setHtmlText(htmlText:String):void{
                isHtml = true;
                setText(htmlText);
            }
            
            /**
             * 重置
             *
             */
            private function reset():void{
                
                this.removeChildren();
                if(originalText != null)
                    imgObjectArr.length=0;
                originalText = "";
            }
            /**
             * 设置文本
             * @param text
             *
             */
            public function setText(text:String):void{
                reset();
                originalText=text;
                if(text==null||text.length<1){
                    trace("the text is has nothing");
                    return;
                }
            
                textStr=StringUtil.DecodingAscIIStr(text);
            
                StringUtil.regExp_allMark.lastIndex=0;
                //判断是否纯文本
                if(!StringUtil.regExp_allMark.test(textStr)){
                    //纯文本
                    isHtml = false;
                    showText(textStr);
                }else{
                    //判断是否有图片标签
                    if(!StringUtil.hasImgTag(textStr)){
                        showText(textStr);
                    }else{
                        //截取图片标签
                        catchImgTag(textStr);
                        textStr=textArr.join("");
                        if(imgObjectArr.length<=0){
                            showText(textStr);
                        }else{
                            showText(textStr,imgObjectArr);
                        }
                    }
                }
            }
            
            /**
             * 获取文本
             * @return
             *
             */
            public function getText():String{
                return originalText;
            }

            /**
             * 显示文本
             * @param text 显示的文本
             * @param SpritesArr 插入文本中的图像信息数组
             *
             */
            private function showText(text:String,SpritesArr:Array=null):void{
                if(text == null || text.length <1)return;
                var textLength:int=0;
                if(tempTf == null){
                    tempTf=createTextField();
                }
                
                if(isHtml){
                    tempTf.htmlText = text;
                }else{
                    if(text) text=text.split("\r").join("\n");
                    tempTf.text=text;
                    if(this._textFormat==null){
                        _textFormat = new TextFormat();
                        _textFormat.font = DEFAULT_FONT
                        _textFormat.font=DEFAULT_FONT;
                    }
                    tempTf.setTextFormat(this._textFormat,0,tempTf.length);
                }
                
                textLength = tempTf.length;
                if(SpritesArr!=null){
                    insertSpritesPlaceholder(SpritesArr,textLength);
                    loadImages(SpritesArr);
                }else{
                    
                    this.addChild(tempTf);
                    _width=tempTf.width;
                    _height=tempTf.height;
                    this.dispatchEvent(new Event(TextContainer.SETTEXTCOMPLETED));
                }
            }
            
            /**
             *将sprites数组中的显示元素的宽度占位符插入到指定文本的位置,生成一个有占位符的String
             * @param Sprites
             * @param maxIndex 文本最大长度
             *
             */
            
            private function insertSpritesPlaceholder(Sprites:Array,maxIndex:int):void{
                if(Sprites==null)return;
                Sprites.sortOn("index",Array.NUMERIC);
                if(textLineHeight<=0) textLineHeight=10;
                for (var i:int=0;i<Sprites.length;i++){
                    var obj:ImgObject=Sprites[i] as ImgObject;
                    if(obj.index<0||obj.index>maxIndex){
                        obj.index=maxIndex;
                        Sprites.splice(i,1);
                        Sprites.push(obj);
                        i--;
                        continue;
                    }
                    var ai:int=insertASPlaceholder(obj);
                
                    if(ai>0){
                        for(var j:int=i+1;j<Sprites.length;j++){
                            Sprites[j].index+=1;
                        }
                        maxIndex+=1;
                    }
                    maxIndex+=1;
                }
            }
            
            /**
             *生成一个obj位置的占位符
             * @param obj
             *
             */
            private function insertASPlaceholder(obj:Object):int{
                if(obj==null ||!(obj is ImgObject))
                    throw Error("The object is not ImgObject");
                var imgObj:ImgObject=obj as ImgObject;
                
                if(imgObj.imgWidth>this._maxWidth){
                    var whRate:Number=imgObj.imgWidth/imgObj.imgHeight;
                    imgObj.imgWidth=this._maxWidth-margins;
                    imgObj.imgHeight=Math.round(imgObj.imgWidth/whRate);
                }
                var index:int=imgObj.index;
                
                var format:TextFormat=CalcPlaceholderFormat(imgObj.imgWidth,textLineHeight);
                var tpindex:Number=0;
                var ct:TextField= createTextField();
                var addIndex:int=0;
                ct.defaultTextFormat=tempTf.defaultTextFormat;
                for(var i:int=0;i<tempTf.numLines;i++){
                    if(tempTf.getLineOffset(i)<=index&&index<=tempTf.getLineLength(i)+tempTf.getLineOffset(i)){
                         ct.text=tempTf.getLineText(i).slice(index-tempTf.getLineOffset(i)+1,tempTf.getLineLength(i));
                        if((Number(format.letterSpacing)+tempTf.getLineMetrics(i).width-ct.getLineMetrics(0).width)>tempTf.width){
                            tempTf.replaceText(index,index,"\r");
                            addIndex=1;
                            index+=addIndex;
                        }
                        break;
                    }
                }
                
                imgObj.index=index;
                tempTf.replaceText(index,index,_placeholder);
                tempTf.setTextFormat(format,index,index+1);
                return addIndex;
            }
            
            /**
             * 计算显示元素的占位符的文本格式(若使用不同的占位符,可重写此方法)。
             * @param    width 宽度。
             * @param    height 高度。
             * @return
             */
            private function CalcPlaceholderFormat(Number, height:Number):TextFormat
            {
                var format:TextFormat = new TextFormat();
                format.font = "Tahoma";
                format.color = _placeholderColor;
                format.size =Math.round( height + 2 * _placeholderMarginV);        
                _formatCalculator.setTextFormat(format);
                var metrics:TextLineMetrics = _formatCalculator.getLineMetrics(0);
                
                format.letterSpacing =Math.ceil( width - metrics.width + 2 * _placeholderMarginH);
                format.underline = format.italic = format.bold = false;
                return format;
            }
            
            /**
             * 将图像<img>html代码从文本中分离出来,将其存进一个imgObject中,
             * 在插入图像时从imgObject获取它在文本中的位置
             */
            private function catchImgTag(text:String):void{
                
                var imgTagArr:Array;
                imgObjectArr.length=0;
                textArr.length=0;
                if(StringUtil.hasImgTag(text)){
                    imgTagArr=text.match(StringUtil.regExp_IMG);
                    textArr=text.split(StringUtil.regExp_IMG);
                    if(isHtml){
                        //如果是html文本,需要先将其转成普通文本
                        //否则html标签都会被当成字符,影响字符位置的计算
                        //同时要将<img>标签转成非html标签
                        for(var i:int=0;i<imgTagArr.length;i++){
                            text=text.replace(imgTagArr[i],"[IMG]");
                        }
                        var temp:TextField = createTextField();
                        temp.htmlText = text;
                        text = temp.text;
                    }
                    //创建图像信息对象
                    for(var i:int=0;i<imgTagArr.length;i++){
                        var imgObj:ImgObject=new ImgObject();
                        imgObj.imgXml=XML(imgTagArr[i]);
                        imgObj.id=imgObj.imgXml.@id;
                        imgObj.imgWidth=imgObj.imgXml.@width;
                        imgObj.imgHeight=imgObj.imgXml.@height;
                        imgObj.src=imgObj.imgXml.@src;
                        //计算图像在文本中的位置,用于之后的插入图像
                        if(isHtml){
                            imgObj.index = text.indexOf("[IMG]")+i
                            text=text.replace("[IMG]","");
                        }else{
                            imgObj.index=text.indexOf(imgTagArr[i])+i;
                            text=text.replace(imgTagArr[i],"");
                        }
                        
                        imgObjectArr.push(imgObj);
                    }
                }
            }
            
            //加载图像数据
            private function loadImages(SpritesArr:Array):void{
                loadOtImages(SpritesArr,0);
            }
            
            /**
             * 循环加载图像数组
             * @param SpritesArr 图像信息数组
             * @param index 加载数组中的项索引
             *
             */

            private function loadOtImages(SpritesArr:Array,index:int):void{
        
                if(index<0||index>SpritesArr.length-1){
                    //这里要调用另一个方法,在加载完成后调用
                    replacePlaceholderToImg(SpritesArr);
                    return;
                }
                
                var imgObj:ImgObject=SpritesArr[index] as ImgObject;
                
                loadImgComplete=function(dobj:DisplayObject):void{OnCompleteHander(dobj,imgObj,SpritesArr,index)};
                loadIoError=function (){OnIOErrorHandler(SpritesArr,index)};
                LoaderPool.getInstance().load(imgObj.src,loadImgComplete,loadIoError);
            }
            
            private function OnCompleteHander(dobj:DisplayObject,imgObj:ImgObject,SpritesArr:Array,index:int):void{
                if(imgObj!=null && dobj != null && (dobj is Bitmap)){
                    //imgObj.image=e.target.content as Bitmap;
                    
                    imgObj.image = cloneBMP(dobj as Bitmap);
                    if(imgObj.image!=null){
                        if(imgObj.imgWidth<imgObj.image.width||imgObj.imgHeight<imgObj.image.height){
                            imgObj.image.width=imgObj.imgWidth;
                            imgObj.image.height=imgObj.imgHeight;
                        }
                    }
                    index++;
                    loadOtImages(SpritesArr,index);
                }
            }
            
            private function cloneBMP(bmp:Bitmap):Bitmap{
                if(bmp == null) return null;
                var bmp:Bitmap = new Bitmap(bmp.bitmapData,bmp.pixelSnapping,bmp.smoothing);
                return bmp;
            }
            
            private function OnIOErrorHandler(SpritesArr:Array,index:int):void{
                ImgObject(SpritesArr[index]).image=null;
                index++;
                loadOtImages(SpritesArr,index);
            }
            
            /**
             * 该方法要实现的功能就是从tempTf中分离出有图片所在的那一行文本,从新调整当行的高度和图片的位置,然后再将其插入之前文本所在的位置
             * 根据textField获取每一行的长度(getLineLength)和每行第一个字符索引(getLineOffset)来确定图片所在的行,再用getLineText获取该行
             * 的文本保存到一个新的textField中,该textField的format要与原来的相同。
             *  
             * @return
             *
             */        
            
            private function replacePlaceholderToImg(sprites:Array):void{
                
                var currentLine:int=0; //当前行
                var currentLineStarIndex:int=0; //当前行第一个索引
                var currentLineEndIndex:int=0; //当前行最后一个索引
                var imgLine:int=0;//图片所在文本行
                var tfLineInfo:Object=new Object();
                var imgObj:ImgObject;
                var flag:Boolean=false;
                var tempSprite:Sprite;
                var currentImgs:Array=new Array();
                var heightPos:Number;
                
                sprites.sortOn("index",Array.NUMERIC);
                //创建一个textfield
                var tfpa:TextField=createTextField();
                tfpa.defaultTextFormat=tempTf.defaultTextFormat;
                heightPos=0;
        
                var htmlList:Array;
                htmlList= tempTf.htmlText.match(StringUtil.regExp_P);
                currentLineStarIndex = 0;
                for(var i:int=0;i<htmlList.length;i++){
                    currentLine=i;
                    var tfitem:TextField=createTextField();
                    
                    tfitem.htmlText = htmlList[i];
                    currentLineStarIndex = currentLineEndIndex + (i==0?0:1);
                    currentLineEndIndex= currentLineStarIndex + tfitem.length-1;
                    currentImgs.length=0;
                    for(var j:int=0;j<sprites.length;j++){
                        imgObj=(sprites[j] as ImgObject);
                        if(currentLineStarIndex<=imgObj.index&&currentLineEndIndex>=imgObj.index){
                            //如果该行有图片,创建一个sprite,该sprite的高是图片的高度,宽度是textfield的宽
                            if(imgObj.image!=null){
                                tfitem.setTextFormat(tempTf.getTextFormat(imgObj.index,imgObj.index+1),imgObj.index-currentLineStarIndex,imgObj.index-currentLineStarIndex+1);
                                currentImgs.push(imgObj);
                                flag=true;
                            }else{
                                //trace(tfitem.text);
                                //tfitem.replaceText(imgObj.index-currentLineStarIndex,imgObj.index-currentLineStarIndex+1,"");
                                //trace(tfitem.text)
                                //tempTf.replaceText(index,index,"\r");
                            }
                        }
                    }
                    
                    //如果该行有图片再创建一个新的textfield继续下一个循环
                    var spriteHeight:Number;
                    
                    if(tfpa != null){
                        tfpa.defaultTextFormat=tempTf.defaultTextFormat;
                    }
                    if(flag){
                        currentImgs.sortOn("imgHeight",Array.NUMERIC);
                        tempSprite=new Sprite();
                        spriteHeight=currentImgs[currentImgs.length-1].imgHeight>tfitem.textHeight?currentImgs[currentImgs.length-1].imgHeight:tfitem.textHeight;
                        spriteHeight=spriteHeight;
                        currentImgs.sortOn("index",Array.NUMERIC);
                        tempSprite.addChild(tfitem);
                        tfitem.x=0;
                        tfitem.y=spriteHeight-tfitem.height+tfitem.getLineMetrics(0).leading;
                        for(var k:int=0;k<currentImgs.length;k++){
                            var rect:Rectangle =tfitem.getCharBoundaries(currentImgs[k].index-currentLineStarIndex);    
                            if (rect != null)
                            {
                                currentImgs[k].image.x = (rect.x + (rect.width - currentImgs[k].image.width) * 0.5 + 0.5) >> 0;
                                currentImgs[k].image.y=spriteHeight-currentImgs[k].imgHeight;
                                tempSprite.addChild(currentImgs[k].image);
                            }
                        }
                        tempSprite.x=0;
                        tempSprite.y=heightPos;
                        heightPos=tempSprite.y+tempSprite.height;
                        this.addChild(tempSprite);
                        tfpa=createTextField();
                        flag=false;
                    }
                    else if(!this.contains(tfpa)){
                        tfpa.htmlText = tfpa.htmlText +tfitem.htmlText;
                        tfpa.x=0;
                        tfpa.y=heightPos;
                        this.addChild(tfpa);
                        heightPos=tfpa.y+tfpa.height;
                    }else{
                        tfpa.htmlText = tfpa.htmlText +tfitem.htmlText;
                        heightPos=tfpa.y+tfpa.height;
                    }
                    
                    if(i>0){
                        _width=maxWidth;
                    }else{
                        _width=tfitem.width;
                    }
                    
                    _height=super.height;
                }
                this.dispatchEvent(new Event(TextContainer.SETTEXTCOMPLETED));
            }
            
            public function update():void{
                if(originalText!=null&&(originalText!=""||originalText.length>0)){
                    setText(originalText);
                }
            }

        
            
            /**
             * 创建新的TextField对象
             * @return
             *
             */
            private function createTextField():TextField{
                var tf:TextField=new TextField();
                tf.width=_maxWidth;
                tf.autoSize=TextFieldAutoSize.LEFT;
                tf.multiline=true;
                tf.wordWrap=true;
                if(_textFormat!=null){
                    tf.defaultTextFormat=_textFormat;
                }else{
                    _textFormat=new TextFormat();
                    _textFormat.font=DEFAULT_FONT;
                    tf.defaultTextFormat=_textFormat;
                }
                return tf;
            }


            /**
             * 获取默认的文本格式
             * @return
             *
             */
            public function get defalutFormat():TextFormat
            {
                return _textFormat;
            }
            
            /**
             * 设置默认的文本格式
             * @return
             *
             */
            public function set defalutFormat(value:TextFormat):void
            {
                _textFormat = value;
                update();
            }

            /**
             * 获取宽度最大值
             * @param value
             *
             */
            public function get maxWidth():Number
            {
                return _maxWidth;
            }

            /**
             * 设置宽度最大值
             * @param value
             *
             */
            public function set maxWidth(value:Number):void
            {
                _maxWidth = value;
                update();
            }
            
            
            override public function get height():Number
            {
                return _height;
            }
            
            override public function set height(value:Number):void{
                
                //_height = value;
                throw new Error("不能直接设置TextContainer的高度");
            }
            
            override public function get width():Number
            {
                return _width;
            }
            
            override public function set width(value:Number):void{
                //_width = value;
                throw new Error("不能直接设置TextContainer的宽度,请用maxWidth设置最大宽度");
            }

        }
    }

  • 相关阅读:
    D 最熟悉的陌生人 (纪念当年就读的梅州市江南高级中学)
    C 最熟悉的陌生人 (纪念当年就读的梅州市江南高级中学)
    B 最熟悉的陌生人 (纪念当年就读的梅州市江南高级中学)
    A 最熟悉的陌生人 (纪念当年就读的梅州市江南高级中学)
    奥秘月球背面
    嫦娥二号月球图片
    外星人就在月球背面
    月球背面
    分享一个绿色版本 sql server 查询器,
    java 8 原版 api 下载地址,
  • 原文地址:https://www.cnblogs.com/skybdemq/p/2574893.html
Copyright © 2011-2022 走看看