部分关键代码与思路参考 http://www.cocoachina.com/bbs/read.php?tid=218977&page=1

感谢原作者 i7909

代码下载地址:https://github.com/chenquanjun/Quick-x-RichLabel

----------------------

cocos2dx支持的文本显示模式比较单一,不支持图文混排与彩色文本。刚好项目要用到彩色文本,所以写了一个简单的类来实现

  • 一、介绍

支持功能

1、图文混排

2、多彩文字混排,支持定义颜色,大小,字体等等属性

3、支持标签内嵌

4、支持自动换行

5、文字fadeIn动画效果(因为是单个字符创建成精灵,可扩展成各种动画效果)

6、支持改变文字,改变文字整体尺寸(其实是宽度)

用于聊天系统、公告或装备描述性文本块(抄原作者的话啦)

还可以用作人物对话,类似Galgame的人物对话(咳咳)

  • 二、原理

1、字符串定义/规则

(1)彩色文本以[fontColor=xx]开头,[/fontColor]结尾,若要改变字体大小,字体类型等等,在开头框中加入对应的关键字(不需要加入关键字结尾),例如:

local str = "[fontColor=ff7f00 fontName=ArialRoundedMTBold fontSize = 30]测试[/fontColor]" --创建颜色为ff7f00,字体名为ArialRoundedMTBold,大小为30的测试 label

文本支持参数 fontColor, fontSize, fontName等等

(2)图片以[image=xx.png]开头,[/image]结尾,例如图片支持参数 image(必须), scale

local imageStr = "[image=test.png scale = 1.2][/image]" --创建文件名为test.png的精灵,大小为1.2

(3)支持图文混排,例如

local multiStr = "[fontColor=42426f]哈哈哈哈哈哈!![/fontColor][image=wsk1.png scale=1.3][/image]"

2、实现原理

(1)字符串解析

1.将字符串以标签头[]为关键字分隔字符串

    local clumpheadTab = {} -- 标签头
--作用,取出所有格式为[xxxx]的标签头
for w in string.gfind(str, "%b[]") do
if string.sub(w,,) ~= "/" then-- 去尾
table.insert(clumpheadTab, w)
end
end

标签头分割

2.标签解析

原理就是将标签的定义属性一个个分离出来然后以table来储存

    -- 解析标签
local totalTab = {}
for k,ns in pairs(clumpheadTab) do
local tab = {}
local tStr
-- 第一个等号前为块标签名
string.gsub(ns, string.sub(ns, , #ns-), function (w)
local n = string.find(w, "=")
if n then
local temTab = self:stringSplit_(w, " ") -- 支持标签内嵌
for k,pstr in pairs(temTab) do
local temtab1 = self:stringSplit_(pstr, "=") local pname = temtab1[] if k == then
tStr = pname
end -- 标签头 local js = temtab1[] local p = string.find(js, "[^%d.]") if not p then
js = tonumber(js)
end local switchState = {
["fontColor"] = function()
tab["fontColor"] = self:convertColor_(js)
end,
} --switch end local fSwitch = switchState[pname] --switch 方法 --存在switch
if fSwitch then
--目前只是颜色需要转换
local result = fSwitch() --执行function
else --没有枚举
tab[pname] = js
return
end
end
end
end)
if tStr then
-- 取出文本
local beginFind,endFind = string.find(str, "%[%/"..tStr.."%]")
local endNumber = beginFind-
local gs = string.sub(str, #ns+, endNumber)
if string.find(gs, "%[") then
tab["text"] = gs
else
string.gsub(str, gs, function (w)
tab["text"] = w
end)
end
-- 截掉已经解析的字符
str = string.sub(str, endFind+, #str)
table.insert(totalTab, tab)
end
end

标签解析

(2)字符分隔

主要用了Unicode编码的原理分隔字符串,此处就不展开了

简单来说就是每个字符的第一位定义了该字符占据了多少字节。这个可以用排队来理解,如果每个人都一样体型的话,n个人的队列长度是一定的,但是如果有些人长得胖有些人长得瘦,那么队列的长度就不确定了,于是乎我们定了一个规则

最瘦的占1个空间,比较瘦的占2个空间,如此类推,只要在范围内的都固定相同空间,然后在头上贴个标签说明他是哪个分段的。这样的话我们只要不断读取他们的头(-,-),就可以把他们分出来了。

    local list = {}
local len = string.len(str)
local i =
while i <= len do
local c = string.byte(str, i)
local shift =
if c > and c <= then
shift =
elseif (c >= and c <= ) then
shift =
elseif (c >= and c <= ) then
shift =
elseif (c >= and c <= ) then
shift =
end
local char = string.sub(str, i, i+shift-)
i = i + shift
table.insert(list, char)
end
return list, len

字符分隔

(3)精灵创建

前面已经把字符串都分割成单个字符了,这里就是简单的创建精灵了,因为只有两种,所以区分一下用label还是sprite来创建即可

--创建精灵
function RichLabel:createSprite_(parseArray)
local spriteArray = {} for i, dic in ipairs(parseArray) do
local textArr = dic.textArray
if #textArr > then --创建文字
local fontName = dic.fontName or self._fontName
local fontSize = dic.fontSize or self._fontSize
local fontColor = dic.fontColor or self._fontColor
for j, word in ipairs(textArr) do
local label = CCLabelTTF:create(word, fontName, fontSize)
label:setColor(fontColor)
spriteArray[#spriteArray + ] = label
self._containLayer:addChild(label)
end
elseif dic.image then
local sprite = CCSprite:create(dic.image)
local scale = dic.scale or
sprite:setScale(scale)
spriteArray[#spriteArray + ] = sprite
self._containLayer:addChild(sprite)
else
error("not define")
end
end return spriteArray
end

创建精灵

(4)位置调整

字符串解析和位置调整是richlabel实现的关键,主要是通过实际创建精灵然后获得精灵的大小,然后按顺序"填"到指定的区域之中,遇到边界则换行

--获得每个精灵的位置
function RichLabel:getPointOfSprite_(widthArr, heightArr, dimensions)
local totalWidth = dimensions.width
local totalHight = dimensions.height local maxWidth =
local maxHeight = local spriteNum = #widthArr --从左往右,从上往下拓展
local curX = --当前x坐标偏移 local curIndexX = --当前横轴index
local curIndexY = --当前纵轴index local pointArrX = {} --每个精灵的x坐标 local rowIndexArr = {} --行数组,以行为index储存精灵组
local indexArrY = {} --每个精灵的行index --计算宽度,并自动换行
for i, spriteWidth in ipairs(widthArr) do
local nexX = curX + spriteWidth
local pointX
local rowIndex = curIndexY local halfWidth = spriteWidth * 0.5
if nexX > totalWidth and totalWidth ~= then --超出界限了
pointX = halfWidth
if curIndexX == then --当前是第一个,
curX = -- 重置x
else --不是第一个,当前行已经不足容纳
rowIndex = curIndexY + --换行
curX = spriteWidth
end
curIndexX = --x坐标重置
curIndexY = curIndexY + --y坐标自增
else
pointX = curX + halfWidth --精灵坐标x
curX = pointX + halfWidth --精灵最右侧坐标
curIndexX = curIndexX +
end
pointArrX[i] = pointX --保存每个精灵的x坐标 indexArrY[i] = rowIndex --保存每个精灵的行 local tmpIndexArr = rowIndexArr[rowIndex] if not tmpIndexArr then --没有就创建
tmpIndexArr = {}
rowIndexArr[rowIndex] = tmpIndexArr
end
tmpIndexArr[#tmpIndexArr + ] = i --保存相同行对应的精灵 if curX > maxWidth then
maxWidth = curX
end
end local curY =
local rowHeightArr = {} --每一行的y坐标 --计算每一行的高度
for i, rowInfo in ipairs(rowIndexArr) do
local rowHeight =
for j, index in ipairs(rowInfo) do --计算最高的精灵
local height = heightArr[index]
if height > rowHeight then
rowHeight = height
end
end
local pointY = curY + rowHeight * 0.5 --当前行所有精灵的y坐标(正数,未取反)
rowHeightArr[#rowHeightArr + ] = - pointY --从左往右,从上到下扩展,所以是负数
curY = curY + rowHeight --当前行的边缘坐标(正数) if curY > maxHeight then
maxHeight = curY
end
end self._maxWidth = maxWidth
self._maxHeight = maxHeight local pointArrY = {} for i = , spriteNum do
local indexY = indexArrY[i] --y坐标是先读取精灵的行,然后再找出该行对应的坐标
local pointY = rowHeightArr[indexY]
pointArrY[i] = pointY
end return pointArrX, pointArrY
end

位置调整

  • 三、测试

测试(1):改变大小 (浅灰色的是设置的尺寸,深灰色的是文字实际的尺寸)

目前仅实现了宽度适应

测试(2)设置文字测试

测试(3)动画测试

[Quick-x]cocos2dx下的彩色文本显示--RichLabel的更多相关文章

  1. CSS 单行溢出文本显示省略号...的方法(兼容IE FF)(转)

    http://www.52css.com/article.asp?id=602 ===================================================     html ...

  2. Cocos2d-x下Lua调用自定义C++类和函数的最佳实践[转]

    Cocos2d-x下Lua调用C++这事之所以看起来这么复杂.网上所有的文档都没讲清楚,是因为存在5个层面的知识点: 1.在纯C环境下,把C函数注册进Lua环境,理解Lua和C之间可以互相调用的本质 ...

  3. 【转】Cocos2d-x下Lua调用自定义C++类和函数的最佳实践

    转自:http://segmentfault.com/blog/hongliang/1190000000631630 关于cocos2d-x下Lua调用C++的文档看了不少,但没有一篇真正把这事给讲明 ...

  4. Android开发之多线程下载、断点续传、进度条和文本显示

    代码实现了在Android环境下的多线程下载.断点续传.进度条显示和文本显示百分数: import java.io.BufferedReader; import java.io.File; impor ...

  5. cocos2d-x 3.0 final 中文显示

    cocos2d-x 3.0的中文显示非常easy,首先,你须要一个xml文件保存中文,还须要一个能显示中文的TTF文件 <?xml version="1.0" encodin ...

  6. 10分钟 教你学会Linux/Unix下的vi文本编辑器

    10分钟 教你学会Linux/Unix下的vi文本编辑器 vi编辑器是Unix/Linux系统管理员必须学会使用的编辑器.看了不少关于vi的资料,终于得到这个总结.不敢独享,和你们共享. 首先,记住v ...

  7. css 溢出文本显示省略号

    这个标题其实已经是一个老生常谈的问题了.很多时候,比如网站最基本的文章列表,标题会很长,而显示列表的区域宽度却没有这么宽,这时候最正常的做法就是 让超出宽度的部分文字用省略号(…)来表示.通常做法是网 ...

  8. EmWin 文本显示函数

    函数模型----------------------------------- 1:void GUI_DispChar(U16 c):  在当前窗口的当前文本位置处,使用当前字体显示单个字符.  c ...

  9. Linux命令行下的vim文本编辑器

    Linux命令行下的vim文本编辑器 下面这个网站的地址讲解的非成分清楚!!!! http://blog.csdn.net/niushuai666/article/details/7275406 学习 ...

随机推荐

  1. WPF学习01:初始XAML浅析

    本文内容: 浅析WPF应用默认创建的XAML中元素.attributes. 新建WPF工程“HelloWPF”. 初始创建的主窗体XAML代码如下: <Window x:Class=" ...

  2. Java从入门到精通——数据库篇之OJDBC版本区别

    classes12.jar,ojdbc14.jar,ojdbc5.jar和ojdbc6.jar的区别,之间的差异 在使用Oracle JDBC驱动时,有些问题你是不是通过替换不同版本的Oracle  ...

  3. MySQL 库大小、表大小、索引大小查询命令

    1.进去指定schema 数据库(存放了其他的数据库的信息)     mysql> use information_schema; 2.查询所有数据的大小      mysql> sele ...

  4. Log4j详细使用教程

    日志是应用软件中不可缺少的部分,Apache的开源项目log4j是一个功能强大的日志组件,提供方便的日志记录.在apache网站:jakarta.apache.org/log4j 可以免费下载到Log ...

  5. Java 8 VM GC Tuning Guide Charter2

    第二章 Ergonomics Ergonomics is the process by which the Java Virtual Machine (JVM) and garbage collect ...

  6. WPF 多线程处理(5)

    WPF 多线程处理(1) WPF 多线程处理(2) WPF 多线程处理(3) WPF 多线程处理(4) WPF 多线程处理(5) WPF 多线程处理(6) 项目的目录: 以下是FileStroage的 ...

  7. Vbox下linux虚拟机根分区扩容

    前言 使用一段时间VBox中的linux后可能会显示根分区空间不足的情况,需要扩容. 通过查阅相关资料,VBox中linux扩容主要有两种办法:通过lvm扩容和通过gparted扩容 LVM条件:VB ...

  8. 网站常用css必备css reset

    在我们写前端代码页面的时候,很多常用的CSS类都是固定的!但没有一个标准或者大家都按自己的方式去随意的写,这样就每次都重复写一些固定的类! 为此HTML5 Doctor(HTML5医生)为我们总结了一 ...

  9. centos6.5\win7双系统安装配置

    一.安装所需软件 1.分区助手专业版PACNPro.exe(必需):用来对硬盘分区,将磁盘的一部分格式化成Linux可以识别的ext3格式 2.Ext2Fsd(硬盘安装必需,光盘安装不用):因为Win ...

  10. 【锋利的JQuery-学习笔记】Tootip(提示框)

    效果图: 1.当鼠标移动到超链接时,有提示框. 2..当鼠标移动到图片动画旋转 html: <div id="jnNotice"> <div id="j ...