[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 学习 ...
随机推荐
- Is C# a clone of a Microsoft replacement for Java?
Is C# a clone of a Microsoft replacement for Java?Let's look at what Anders Hejlsberg Said. Hejlsber ...
- 1107. Social Clusters (30)
When register on a social network, you are always asked to specify your hobbies in order to find som ...
- mysql 配置主从
1.选择2个ip,1个为主,1个为从:例:主:192.168.12.76 从:192.168.12.772.在192.168.12.76的my.cnf 配置master,添加如下:(红色为添加的内容) ...
- redis常见性能问题和解决方案?
Master写内存快照,save命令调度rdbSave函数,会阻塞主线程的工作,当快照比较大时对性能影响是非常大的,会间断性暂停服务,所以Master最好不要写内存快照. Master AOF持久化, ...
- 20145120 《Java程序设计》第3周学习总结
20145120 <Java程序设计>第3周学习总结 教材学习内容总结 基本类型与类类型的概念 在java里使用数组和字符串 封装的概念 在java定义函数 重载的概念 static的概念 ...
- C#中Linq查询基本操作
摘要:本文介绍Linq查询基本操作(查询关键字) - from 子句 - where 子句 - select子句 - group 子句 - into 子句 - orderby 子句 - join 子句 ...
- 在ubuntu16.04 下安装haproxy 1.5.11 做tcp负载均衡
由于haproxy需要FQ下载,所以从csdn下载了较为新版的haproxy1.5.11,安装过程如下: 1. 解压haproxy-1.5.11.tar.gz : tar xzvf haproxy-1 ...
- Python的map、filter、reduce函数 [转]
1. map函数func作用于给定序列的每个元素,并用一个列表来提供返回值. map函数python实现代码: def map(func,seq): mapped_seq = [] fo ...
- java 连接池的简单实现
最近一个项目中需要自己写个连接池, 写了一个下午,挺辛苦的,但不知道会不会出问题, 所以,贴到博客上,欢迎各路大神指点 1. 配置信息: /** * */ package cn.mjorcen.db. ...
- Problem 1016 咒文卷轴 优先队列+前缀和+rmq
题目链接: 题目 Problem 1016 咒文卷轴 Time Limit: 3000 mSec Memory Limit : 131072 KB 问题描述 小Y 是一个魔法师,有一天他获得了一卷神秘 ...