cocos2dx-lua 简单的字体变色拼接实现
这里主要做的是游戏公告里面用到的,因此我加入了简单的html <font>标签解析,是为了给运营小白预览,但其中的size 属性没有,因为后来没有这个需求了,所以也就懒得改了。
实现思路很简单:设置好行宽和行高,然后一个一个字往上面添加,直到达到行宽上限或者换行符,就换行,再循环。
--简易html label --[[ 暂只对以下标签进行实现 <font> 标签进行实现,可添加 size 和 color属性 <br> 换行 --]] --[=[ demo: html = "<font size=\"50\" color=\"#ff0000\" > ab,casdjfladfasdgasdasdgasdfasdfqwetqwetrtwqrtqwerqwerqwerqwetqwetqwerqwerqwer44444444444222222222asdugowe<br>iurlsdjlkasdhga </font><font size=\"28\" color=\"#002\" > ab,21<br>iurlsdjlkasdhga </font><font size=\"22\" color=\"#2231\" > ab,12<br>12 </font><font size=\"10\" color=\"#2202\" > ab,.21<br>1 </font>" local lable = require ("common.HtmlLabel").new(600,html) lable:setPosition(400,400) self._lay:addChild(lable) --]=] local HtmlLabel = class("HtmlLabel",function() return Layout:create() end) function HtmlLabel:ctor(width , html) self._width = width self._height = 0 self._defaultFontSize = 18 self._defaultFontColor = 0x000000 self:initWithString(html) end local headTag = "<font .->" local lastTag = "</font>" function HtmlLabel:initWithString(html) self._html = string.lower(html) self:removeAllChildrenWithCleanup(true) local labelList = {} html = string.gsub(html , "<br>" , "\n") while string.len(html) > 0 do local bPos,ePos = string.find(html,lastTag) local node = {} local headTagEndPos = 1 if not find then local hbPos,hePos = string.find(html,headTag) if hbPos then -- local head = string.sub(html , hbPos , (hePos-hbPos+1)) local head = string.sub(html , hbPos+5 , (hePos-1)) head = string.gsub(head , "#" , "0x") head = string.gsub(head , "(%d\")" , "%1,") local strFunc = " return {" .. head .. "}" node = assert(loadstring(strFunc))() if not node.color then node.color = self._defaultFontColor else node.color = tonumber(node.color) end if not node.size then node.size = self._defaultFontSize else node.size = tonumber(node.size) end headTagEndPos = hePos + 1 -- html = string.sub(html, hePos+1 , string.len(html)) else node.color = self._defaultFontColor node.size = self._defaultFontSize end node.str = string.sub(html,headTagEndPos,bPos-1) html = string.sub(html , ePos+1 , string.len(html)) --去除已处理段 else node.str = html node.color = self._defaultFontColor node.size = self._defaultFontSize html = "" end table.insert(labelList , node) end if #labelList == 0 then return end local node1 = labelList[1] self:initRichLabel(node1.str,self._width ,node1.size*(1+0.2) , node1.size , ccc3(math.floor(node1.color/0x10000), math.floor(node1.color/0x100)%0x100 , node1.color % 0x100 )) for i=2,#labelList do node1 = labelList[i] -- print ("%02x%02x%02x",math.floor(node1.color/0x10000), math.floor(node1.color/0x100)%0x100 , node1.color % 0x100 ) self:addString(node1.str, ccc3(math.floor(node1.color/0x10000), math.floor(node1.color/0x100)%0x100 , node1.color % 0x100 )) end end function HtmlLabel:initRichLabel(content ,lineWidth , lineHeight , fntSize , color) self.lineWidth = lineWidth self.lineHeight = lineHeight self._fntSize = fntSize self._defaultColor = color self.widthIndex = 0 self.rowIndex = 1 self.nodeList = {} self.anchorPoint = ccp(0.5,0.5) self:addString(content) end --重新设置一个string function HtmlLabel:setString(content , color) self:removeAllChildrenWithCleanup(true) self.widthIndex = 0 self.rowIndex = 1 self.nodeList = {} self._defaultColor = color or self._defaultColor self:addString(content) end --增加一个string function HtmlLabel:addString(labelStr , color) color = color or self._defaultColor if self.widthIndex >= self.lineWidth then self.widthIndex = 0 self.rowIndex = self.rowIndex + 1 end while labelStr ~= nil and labelStr ~= "" do local begIndex,endIndex = self:getMaxSubStr(labelStr,self.lineWidth - self.widthIndex , self._fntSize) if begIndex == nil then --换行 self.widthIndex = 0 self.rowIndex = self.rowIndex + 1 begIndex,endIndex = self:getMaxSubStr(labelStr,self.lineWidth - self.widthIndex, self._fntSize) end local subStr = string.sub(labelStr,begIndex,endIndex) labelStr = string.sub(labelStr,endIndex+1,string.len(labelStr)) local label = Label:create() label:setFontSize(self._fntSize) local text = string.gsub(subStr, "\n", "")--去除换行符 label:setText(text) label:setColor(color) label:setPositionX(self.widthIndex) self:addChild(label) label:setAnchorPoint(ccp(0,0)) label.rowIndex = self.rowIndex label.srcX = self.widthIndex table.insert(self.nodeList,label) self.widthIndex = self.widthIndex + label:getContentSize().width if string.find(subStr , '\n') then --出现强制换行 self.widthIndex = 0 self.rowIndex = self.rowIndex + 1 end end self:updateInset() end function HtmlLabel:setContentSize( w , h) local sz = w if h then sz = CCSize(w ,h ) end self.contentSize = sz end function HtmlLabel:getContentSize() return self.contentSize end --更新容器所有Node的位置 function HtmlLabel:updateInset() local row = self.rowIndex if self.widthIndex == 0 then --如果最后一行还没内容 row = row - 1 end local contentSize = CCSize(self.lineWidth,row*self.lineHeight) local anchorY = contentSize.height * self.anchorPoint.y local anchorX = contentSize.width * self.anchorPoint.x for k,v in pairs(self.nodeList) do v:setPositionY((row-v.rowIndex)*self.lineHeight - anchorY) v:setPositionX(v.srcX - anchorX) end self:setContentSize(contentSize) end --设置锚点 function HtmlLabel:setAnchorPoint( x, y ) local pt = nil if not y then pt = x else pt = ccp(x,y) end if pt.x == self.anchorPoint.x and pt.y == self.anchorPoint.y then return end self.anchorPoint = pt self:updateInset() end function HtmlLabel:setPosition( x , y ) local pt = nil if not y then pt = x else pt = ccp(x,y) end CCNode.setPosition(self,pt) end --获取宽度范围内,最长子串 function HtmlLabel:getMaxSubStr(_string,width,fntSize) local result = "" local index = 1 local is_end = true local index_max = string.len(_string) local label = Label:create() label:setFontSize(fntSize) while is_end do local firstCase = string.byte(_string,index) if firstCase == nil then break end local caseLen = self:sizeof(firstCase) --字符宽度 local strCase = string.sub(_string,index,index + caseLen-1) if strCase == "\n" then result = result .. strCase index = index + caseLen --保留回车返回 break end label:setText(result .. strCase) local t = label:getContentSize().width*label:getScale() if t < width then result = result .. strCase index = index + caseLen else is_end = false end if index>index_max then is_end=false end end if result == "" then return nil end return 1,index-1 end --获取某字符所占字节数 function HtmlLabel:sizeof(firstCase) if (firstCase >= 0 and firstCase <= 0x7f) then return 1 elseif firstCase >= 0x80 and firstCase < 0xe0 then return 2 elseif firstCase >= 0xe0 then return 3 end end function HtmlLabel:getSize() return CCSize(self._width , self._height) end return HtmlLabel
Stay hungry, stay foolish!