[Quick-x]cocos2dx下的彩色文本显示--RichLabel
部分关键代码与思路参考 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的更多相关文章
- CSS 单行溢出文本显示省略号...的方法(兼容IE FF)(转)
http://www.52css.com/article.asp?id=602 =================================================== html ...
- Cocos2d-x下Lua调用自定义C++类和函数的最佳实践[转]
Cocos2d-x下Lua调用C++这事之所以看起来这么复杂.网上所有的文档都没讲清楚,是因为存在5个层面的知识点: 1.在纯C环境下,把C函数注册进Lua环境,理解Lua和C之间可以互相调用的本质 ...
- 【转】Cocos2d-x下Lua调用自定义C++类和函数的最佳实践
转自:http://segmentfault.com/blog/hongliang/1190000000631630 关于cocos2d-x下Lua调用C++的文档看了不少,但没有一篇真正把这事给讲明 ...
- Android开发之多线程下载、断点续传、进度条和文本显示
代码实现了在Android环境下的多线程下载.断点续传.进度条显示和文本显示百分数: import java.io.BufferedReader; import java.io.File; impor ...
- cocos2d-x 3.0 final 中文显示
cocos2d-x 3.0的中文显示非常easy,首先,你须要一个xml文件保存中文,还须要一个能显示中文的TTF文件 <?xml version="1.0" encodin ...
- 10分钟 教你学会Linux/Unix下的vi文本编辑器
10分钟 教你学会Linux/Unix下的vi文本编辑器 vi编辑器是Unix/Linux系统管理员必须学会使用的编辑器.看了不少关于vi的资料,终于得到这个总结.不敢独享,和你们共享. 首先,记住v ...
- css 溢出文本显示省略号
这个标题其实已经是一个老生常谈的问题了.很多时候,比如网站最基本的文章列表,标题会很长,而显示列表的区域宽度却没有这么宽,这时候最正常的做法就是 让超出宽度的部分文字用省略号(…)来表示.通常做法是网 ...
- EmWin 文本显示函数
函数模型----------------------------------- 1:void GUI_DispChar(U16 c): 在当前窗口的当前文本位置处,使用当前字体显示单个字符. c ...
- Linux命令行下的vim文本编辑器
Linux命令行下的vim文本编辑器 下面这个网站的地址讲解的非成分清楚!!!! http://blog.csdn.net/niushuai666/article/details/7275406 学习 ...
随机推荐
- Hadoop管理员的十个最佳实践(转)
前言 接触Hadoop有两年的时间了,期间遇到很多的问题,既有经典的NameNode和JobTracker内存溢出故障,也有HDFS存储小文件问题,既有任务调度问题,也有MapReduce性能问题.遇 ...
- access_ok()
access_ok() 函数是用来代替老版本的 verify_area() 函数的.它的作用也是检查用户空间指针是否可用. 函数原型: access_ok (type, addr, size); 变量 ...
- HTTP 错误 500.21 - Internal Server ErrorHTTP
应用程序“DEFAULT WEB SITE/WINDRP_TB/TBFXWS”中的服务器错误Internet Information Services 7.5错误摘要HTTP 错误 500.21 - ...
- 深入浅出C++引用(Reference)类型
要点1:为反复使用的.冗长的变量名称定义一个简短的.易用的别名,从而简化了代码.通常,冗长的变量名称源于多层嵌套对象,例如类中定义嵌套类,类中定义其它类对象. //------ 未使用引用的程序片段, ...
- 《Dive into Python》Chapter 2 and Chapter 3 笔记
Example 2.1. odbchelper.py def buildConnectionString(params): """Build a connection s ...
- ls 排序
ls 排序 首先我们通过man 来看看 ls其中有几项; -S sort by file size : 按大小降序 --sort=WORD sort by WORD instead of na ...
- HDU 2121 Ice_cream’s world II 不定根最小树形图
题目链接: 题目 Ice_cream's world II Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Ja ...
- myeclipse/eclipse添加Spket插件实现ExtJs4.2/ExtJs3智能提示
前言 感谢luotao,本博客是copy这篇博客的:http://www.cnblogs.com/luotaoyeah/p/3803926.html ,因为太重要了,所以笔者再写一次. 重要说明:ec ...
- oracle——分析函数——排序值分析函数
一.问题描述 查询列表时,我们有时需要对查询结果依据某个字段进行排名. 如果每条记录在排序字段上都不相同,我们可以将原查询作为一个视图,查询其rownum,便可以实现简单排序,例如: select r ...
- NYOJ-44 子串和 AC 分类: NYOJ 2014-01-04 22:53 154人阅读 评论(0) 收藏
作为菜鸟一枚,对子串和的代码完全就是硬算 的..结果是TLE #include<stdio.h> int jh(int x,int y,int num[],int sum[]); int ...