cocos2dx-js 实现自定义富文本

10 篇文章 0 订阅

在做游戏的时候,有一个特殊的需求引擎没有直接提供。

一段Label有一部分是其他颜色,

例如:“一只 优雅   攻城狮




上面这个Label,一般想到的常规方式是 用四个Label拼接,放到不同的位置。

其实RichText是提供了这种功能的,用设置好的四个RichElementText就能实现。但是相对来说比较繁琐,而对于策划来说比较难懂,后来协定的做法是用HTML文本格式来实现这种效果,也就是说给你一段HTML的文本,你就能显示出相应的富文本的格式。

比如:

"<font fontSize=18 color=255,255,0>产生一些正则表达式</font></br><font fontSize=18 color=0,255,82 >随机的碎片</font><font fontSize=18>,提高VIP等级能获得更多免费次数!</font><font fontSize=18 color=255,255,0>产生一些正则表达式</font></br><font fontSize=18 color=0,255,82 >随机的碎片</font>"

上面采取的是简化的HTML,当然其实你可以自己定,相应的代码就会产生变化。

产生的结果如图:


当然一行的长度可以自己控制。


先贴代码,后面再做整理。(这里用到的主要是一些简单的正则表达式和字符串处理,后面还会做优化,有问题一起讨论)

var fontInfo = cc.Class.extend({
    fontName:null,
    fontSize:null,
    color:null,
    opacity:null,
    ctor:function (){
        var self = this;
        self.fontName = "Helvetica";
        self.fontSize = 24.0;
        self.opacity = 255;
        self.color = "255,255,255";
    }
});

//富文本
var SuperRichText = ccui.Widget.extend({
    fontList:null,	//字体列表
    lineList:null,	//RichText列表
    m_line:null,	//当前文本
    m_width:0,
    m_height:0,
    m_max:0,
    m_htmlJsonList:null,
    m_defaultFontSize:18,
    /*
     _width    文本宽度
     _height    文本高度
     _string    字符串
     _pos       位置
     _args      参数替换列表
     _fontSize  默认字体大小
     */
    ctor:function(_width,_height,_string,_pos,_args,_fontSize){
        ccui.Widget.prototype.ctor.call(this);
        var self = this;
        self.fontList = [];
        self.lineList = [];
        self.m_htmlJsonList = [];
        self.setSize(_width,_height);
        self.fontList.push(new fontInfo());
        self.addNewLine();
        if(typeof _pos != "undefined"){
            self.setPosition(_pos);
        }
        if(typeof _args != "undefined"){
            _string = _string.format(_args);
        }
        if(typeof _fontSize != "undefined"){
            self.m_defaultFontSize = _fontSize;
        }
        self.analysisHtml(_string);
        return self;
    },
    setSize:function(_width, _height){
        this.m_width = _width;
        this.m_height = _height;
    },
    renderHtml:function(_json)
    {
        _json = eval(_json);
        var self = this;
        var colorArr= [];
        for(var i in _json)
        {
            var obj = _json[i];
            if(obj.text == "</br>"){
                self.addNewLine();
            }else if(obj.text != ""){
                //添加文字
                colorArr = obj.color.split(',');
                var textElement = new ccui.RichElementText(0, cc.color(parseInt(colorArr[0]), parseInt(colorArr[1]), parseInt(colorArr[2]), parseInt(obj.opacity)), parseInt(obj.opacity), obj.text, obj.fontName, parseInt(obj.fontSize));
                var num = self.m_width/parseInt(obj.fontSize)*2;        //一行能容纳的字数
                var max = self.LengthOfString(obj.text);                //文本长度
                var actualWidth = max*obj.fontSize/2;
                var hang = Math.ceil((self.m_line.actualWidth+actualWidth)/self.m_width);
                self.m_line.actualWidth = parseInt(self.m_line.actualWidth)+actualWidth+obj.fontSize*2;
                self.m_max = parseInt(obj.fontSize)>self.m_max?parseInt(obj.fontSize):self.m_max;       //取字体大的那个
                self.m_line.width = self.m_width-obj.fontSize*2;
                self.m_line.height = hang*Math.ceil(self.m_max+self.m_max/5);
                self.m_line.pushBackElement(textElement);
            }else if(obj.img != ""){
                //添加图片
                colorArr = obj.color.split(',');
                var image = new ccui.RichElementImage(0, cc.color.WHITE, parseInt(obj.opacity), obj.img);
                self.m_line.pushBackElement(image);
            }
        }
        self.updateLine();
    },
    //解析HTML
    analysisHtml:function(_str){
        // 解析属性 (\w+)=([^\s>]+)
        var self = this;

        var curString = _str;
        var begin = curString.search("<font");
        var end = curString.search("</font>");
        if(begin >= 0){
            if(begin > 0){
                var str = curString.slice(0,begin);
                var htmlJson = {};
                htmlJson["fontSize"] = self.m_defaultFontSize;
                htmlJson["color"] = "255,255,255";
                htmlJson["opacity"] = 255;
                htmlJson["fontName"] = res.font;
                htmlJson["text"] = str;
                self.m_htmlJsonList.push(htmlJson);
            }
            while(begin >= 0){
                var htmlText = curString.slice(begin,end+7);
                console.log("htmlText = "+htmlText);
                var attr = htmlText.match(/(\w+)=([^\s>]+)/g);
                var content = htmlText.match(/>.*</)[0];
                var htmlJson = {};
                htmlJson["text"] = content.slice(1,content.length-1);
                if(attr){
                    for(var i in attr){
                        var array = attr[i].split("=");
                        if(array[0] == "fontSize"){
                            htmlJson["fontSize"] = array[1];
                        }else{
                            htmlJson["fontSize"] = self.m_defaultFontSize;
                        }
                        if(array[0] == "color"){
                            htmlJson["color"] = array[1];
                        }else{
                            htmlJson["color"] = "255,255,255";
                        }
                        if(array[0] == "opacity"){
                            htmlJson["opacity"] = array[1];
                        }else{
                            htmlJson["opacity"] = 255;
                        }
                        if(array[0] == "fontName"){
                            htmlJson["fontName"] = array[1];
                        }else{
                            htmlJson["fontName"] = res.font;
                        }
                    }
                }else{
                    htmlJson["fontSize"] = self.m_defaultFontSize;
                    htmlJson["color"] = "255,255,255";
                    htmlJson["opacity"] = 255;
                    htmlJson["fontName"] = res.font;
                }

                self.m_htmlJsonList.push(htmlJson);
                console.log("attr = "+attr);
                curString = curString.slice(end+7,curString.length);
                var brTag = curString.search("</br>");
                if(brTag == 0){
                    //换行
                    var brHtmlJson = {};
                    brHtmlJson["text"] = "</br>";
                    self.m_htmlJsonList.push(brHtmlJson);
                    curString.slice(5,curString.length);
                }
                begin = curString.search("<font");
                end = curString.search("</font>");
            }
        }else{
            var htmlJson = {};
            htmlJson["fontSize"] = self.m_defaultFontSize;
            htmlJson["color"] = "255,255,255";
            htmlJson["opacity"] = 255;
            htmlJson["fontName"] = res.font;
            htmlJson["text"] = _str;
            self.m_htmlJsonList.push(htmlJson);
        }
        self.renderHtml(self.m_htmlJsonList);
        console.log("analysis Ended!");

    },
    //解析属性
    analysisAttr:function(_str){
        var self = this;
    },
    LengthOfString:function(str){
        var len = 0;
        for (var i=0; i<str.length; i++) {
            var c = str.charCodeAt(i);
            //单字节加1
            if ((c >= 0x0001 && c <= 0x007e) || (0xff60<=c && c<=0xff9f)) {
                len++;
            }
            else {
                len+=2;
            }
        }
        return len;
    },
    addNewLine:function(){
        //新加一个RichText
        var self = this;
        self.m_line = new ccui.RichText();
        self.m_line.actualWidth = 0;
        //self.m_line.setSizeType(ccui.Widget.SIZE_ABSOLUTE);
        self.m_line.ignoreContentAdaptWithSize(false);
        self.lineList.push(self.m_line);
        self.addChild(self.m_line);
        self.m_max = 0;
    },
    updateLine:function(){
        //调整RichText位置
        var self = this;
        var maxWidth = 0.0;
        var maxHeight = 0.0;
        for(var i=self.lineList.length-1; i>=0; i--){
            var line = self.lineList[i];
            line.setAnchorPoint(cc.p(0, 0));
            line.formatText();
            var size = line.getContentSize();
            console.log("maxHeight =" +maxHeight);
            line.setPositionY(maxHeight);
            if(size.width>maxWidth){
                maxWidth=size.width;
            }
            maxHeight+=size.height;
        }
        self.setAnchorPoint(cc.p(0, 0));
        self.setContentSize(maxWidth, maxHeight);
    }
});



Cocos2d-x 中的富文本可以通过 RichText 类来实现。RichText 类提供了一种简单的方式来创建并渲染富文本。通过 RichText 可以添加不同的字体、颜色、大小和对齐方式等属性,同时还支持添加图片和超链接等元素。 以下是一个简单的使用 RichText 的示例: ``` auto label = cocos2d::ui::RichText::create(); label->ignoreContentAdaptWithSize(false); label->setContentSize(Size(200, 100)); // 添加文字 auto text = cocos2d::ui::RichElementText::create(1, Color3B::WHITE, 255, "Hello World", "Arial", 12); label->pushBackElement(text); // 添加图片 auto image = cocos2d::ui::RichElementImage::create(2, Color3B::WHITE, 255, "path/to/image.png"); label->pushBackElement(image); // 添加超链接 auto link = cocos2d::ui::RichElementText::create(3, Color3B::YELLOW, 255, "click me", "Arial", 12); link->setUnderline(true); link->setUrl("http://www.example.com"); label->pushBackElement(link); label->setPosition(Vec2(100, 100)); addChild(label); ``` 在上面的示例中,我们创建了一个 RichText 对象,并添加了一些不同类型的元素:文本、图片和超链接。可以通过设置 setContentSize() 方法来指定 RichText 的大小,并使用 pushBackElement() 方法添加元素。元素的类型可以通过创建不同类型的 RichElement 对象来实现。在示例中,我们创建了 RichElementText 、RichElementImage 和 RichElementText 对象,分别表示文本、图片和超链接。 在创建 RichElementText 和 RichElementImage 对象时,需要指定一些属性,例如字体、颜色、大小和路径等。对于超链接,可以使用 setUrl() 方法来指定链接地址,同时还可以设置下划线等样式。 最后,我们将 RichText 添加到场景中,并设置其位置。通过这种方式,就可以轻松地创建和渲染富文本
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值