概述
上一节讲述了CanvasItem内置文本绘制函数,以及TextLine
和TextParagraph
类,绘制单行和多行文本的基础内容。
但是实际上TextLine
和TextParagraph
类比我们想象的要功能丰富和强大的多。本节就来详细介绍一下。
系列目录
- 0.概述
- 1.绘制简单图形
- 2.设定绘图变换
- 3.绘制纹理
- 4.绘制样式盒
- 5.绘制字符和字符串
- 6.TextLine和TextParagraph详解
- 7.自定义节点TextBoard
- 8.绘制点索引
- 9.绘制表格
TextLine详解
制表位的使用
TextLine
提供了tab_align()
方法,可以直接将单行文本与指定的制表位对齐。这也就是制表符和制表位原始的含义和用法。
extends Node2Dvar font = ThemeDB.fallback_font
var pos := Vector2(200,200) # 绘制位置 - 表格左上角点func _draw() -> void:# 构造TextLinevar text = TextLine.new()text.add_string("序号\t姓名\t性别\t年龄",font,16)text.tab_align([50,60,60,200])# 绘制text.draw(get_canvas_item(),pos)
在上面的代码中:
- 我们将字符串
"序号\t姓名\t性别\t年龄"
添加给TextLine
实例 - 然后为
tab_align()
传入[50,60,60,200]
,也就是每列的列宽。
绘制的效果如下:
图文混排
- 当你看到
TextLine
使用add_string()
而不是类似text
的属性,你就知道问题不简单。 - 实际上,
TextLine
确实可以用add_string()
以类似数组的append()
末尾追加的方式分几次构成一个完整的字符串,但是更重要的是配合add_object()
方法,实现图文混排。
以下面的代码为例:
extends Node2Dvar font = ThemeDB.fallback_font
var pos := Vector2(200,200) # 绘制位置 - 表格左上角点
const img0 = preload("res://imgs/0.png")
func _draw() -> void:# 构造TextLinevar text = TextLine.new()text.add_string("前面的文字",font,16)text.add_object(img0,Vector2(36,36),INLINE_ALIGNMENT_BOTTOM,1)text.add_string("后面的文字",font,16)# 绘制text.draw(get_canvas_item(),pos)var rect = text.get_object_rect(img0) # 获取占位矩形大小rect.position += posdraw_texture_rect(img0,rect,false) # 绘制图片
上面的代码中:
- 我们首先用
add_string()
添加了"前面的文字"
- 然后用
add_object()
添加了一个(36,36)
大小的图片占位。 - 然后又用
add_string()
添加了"后面的文字"
- 之后先绘制了文本
- 然后通过
get_object_rect()
获取文本占位的矩形,然后利用draw_texture_rect()
将图片绘制到了占位的矩形处,从而实现最终的图文混排效果
绘制效果:
添加和处理多个图片
- 和
add_string()
一样,我们也可以反复多次使用add_object()
,来创建一个图文混排的单行文本。 - 然后通过
get_objects()
可以获取所有已经添加的占位对象构成的数组,并遍历和绘制。
extends Node2Dvar font = ThemeDB.fallback_font
var pos := Vector2(200,200) # 绘制位置 - 表格左上角点
const img0 = preload("res://imgs/0.png")
const img1 = preload("res://imgs/1.png")
func _draw() -> void:# 构造TextLinevar text = TextLine.new()#text.add_string("前面的文字",font,16)text.add_object(img0,Vector2(36,36),INLINE_ALIGNMENT_BOTTOM,1)text.add_string("后面的文字",font,16)text.add_object(img1,Vector2(16,16),INLINE_ALIGNMENT_BOTTOM,1)text.add_string("后面的文字",font,16)# 绘制text.draw(get_canvas_item(),pos)var objs = text.get_objects()for obj in objs:var rect = text.get_object_rect(obj) # 获取占位矩形大小rect.position += posdraw_texture_rect(obj,rect,false) # 绘制图片
绘制的效果:
绘制下划线
extends Node2Dvar font = ThemeDB.fallback_font
var pos := Vector2(200,200) # 绘制位置 - 表格左上角点
const img0 = preload("res://imgs/0.png")
func _draw() -> void:# 构造TextLinevar text = TextLine.new()#text.add_string("前面的文字",font,16)text.add_object(img0,Vector2(36,36),INLINE_ALIGNMENT_BOTTOM,1)text.add_string("后面的文字",font,16)# 绘制text.draw(get_canvas_item(),pos)text.draw_outline(get_canvas_item(),pos,1,Color.BLACK)# 获取和计算下划线位置var y1 = text.get_size().y + text.get_line_underline_position()var p1 = pos + Vector2(0,y1)var p2 = p1 + Vector2(text.get_line_width(),0)# 绘制下划线draw_line(p1,p2,Color.RED,2)var rect = text.get_object_rect(img0) # 获取占位矩形大小rect.position += posdraw_texture_rect(img0,rect,false) # 绘制图片
TextParagraph详解
TextParagraph
可以看做是TextLine的可自动换行版本。使用方法和思路几乎如出一辙。
图文混排
TextParagraph
也可以实现图文混排。
extends Node2Dvar font = ThemeDB.fallback_font
var pos := Vector2(200,200) # 绘制位置 - 表格左上角点
const img0 = preload("res://imgs/0.png")
const img1 = preload("res://imgs/1.png")
const img2 = preload("res://imgs/2.png")func _draw() -> void:# 构造TextLinevar text = TextParagraph.new()text.width = 150#text.add_string("前面的文字",font,16)text.add_object(img0,Vector2(36,36),INLINE_ALIGNMENT_BOTTOM)text.add_string("后面的文字",font,16)text.add_object(img1,Vector2(16,16),INLINE_ALIGNMENT_BOTTOM)text.add_string("后面的文字",font,16)text.add_object(img2,Vector2(48,48),INLINE_ALIGNMENT_BOTTOM)text.draw(get_canvas_item(),pos)for l in text.get_line_count():var objs = text.get_line_objects(l)for obj in objs:var rect = text.get_line_object_rect(l,obj) # 获取占位矩形大小rect.position += posdraw_texture_rect(obj,rect,false) # 绘制图片
绘制的效果:
逐行绘制
TextParagraph
的本意是文本段落。而不是单纯多行文本的并列。
段落是一个整体,可以因为宽度限制而自动换行。而此时段落就是由多行组成。
TextParagraph
提供了段落层面的操作,也提供了具体行层面的操作。
draw_line
是绘制单行。因此我们可以单独挑选段落中的某一行进行显示,也可以逐行绘制,且设定不同的颜色。
extends Node2Dvar font = ThemeDB.fallback_font
var pos := Vector2(200,200) # 绘制位置 - 表格左上角点func _draw() -> void:# 构造TextLinevar textP = TextParagraph.new()#textP.break_flags = 4textP.width = 150textP.add_string("白日依山尽,黄河入海流。欲穷千里目,更上一层楼。",font,16)# 逐行绘制for l in textP.get_line_count():# 计算累计的行高var h = 0for i in range(l):h += textP.get_line_size(i).y# 构造随机字色var font_color = Color(randf(),randf(),randf(),1)# 绘制当前行textP.draw_line(get_canvas_item(),pos + Vector2(0,h),l,font_color)
逐行绘制效果:
绘制表格数据
和TextLine
一样,TextParagraph
也提供了tab_align()
方法,可以实现将带有制表符\t
的文本渲染为指定列宽的表格形式。
extends Node2Dvar font = ThemeDB.fallback_font
var pos := Vector2(200,200) # 绘制位置 - 表格左上角点var table = """
姓名 性别 年龄
张三 男 35
李四 男 45
"""func _draw() -> void:# 构造TextParagraphvar textP = TextParagraph.new()textP.add_string(table,font,16)textP.tab_align([100,100,100])# 绘制textP.draw(get_canvas_item(),pos)
上面代码中:
table
变量存储了多行文本数据,每行字段和数据之间用Tab键分割,在Godot的代码编辑器中它是以制表符对齐显示的
- 同样通过
tab_align
设定三列的宽度
绘制效果:
总结
- 本节简单补充了一下
TextLine
和TextParagraph
的细节功能,包括图文混排和制表这两个非常重要的功能。 - 其实
add_object()
不仅仅可以添加图片站位来实现图文混排,实际上也可以将控件或某些节点混合到文字中国 - 对于绘制表格,如果想要更细节的控制则不能单单使用
tab_align
和制表符实现。对于更好的表格绘制,可以见后续文章