
本文介绍如何将任意长度的句子按单词拆分、逐行自动适配并水平垂直居中渲染到 Processing 画布上,核心是结合 textAlign(CENTER)、动态行高计算与字符串分段逻辑,确保更换句子后布局仍保持居中。
本文介绍如何将任意长度的句子按单词拆分、逐行自动适配并水平垂直居中渲染到 processing 画布上,核心是结合 `textalign(center)`、动态行高计算与字符串分段逻辑,确保更换句子后布局仍保持居中。
在 Processing 中实现文本居中显示,尤其是多行句子的自动排版,不能仅依赖固定坐标(如 text(riddle, width/2, height/2)),因为 text() 默认以左基线为锚点,且长句会溢出画布。真正稳健的方案需满足三点:按空格分词 → 按宽度限制拼接成行 → 每行独立居中绘制 → 行间垂直对齐可控。以下教程将逐步实现这一目标。
✅ 核心思路:分而治之 + 动态定位
- 文本分段:将原始句子按空格切分为单词数组,再根据预设最大字符数(或更优的像素宽度)合并为多行短字符串;
- 居中渲染:启用 textAlign(CENTER),使每行文本以画布水平中心为基准绘制;
- 垂直布局:用累加的 y 坐标控制行间距,起始位置需偏移以保证整体视觉居中(例如从画布垂直中点向上偏移若干行高)。
? 实现分段逻辑:TextSplitter 工具类
虽然示例中使用了简单的字符长度阈值(如 12),但实际开发中建议升级为基于 textWidth() 的像素级分段(见文末优化提示)。当前简洁版如下:
public static class TextSplitter {
public static ArrayList<string> splitText(String inputText, int maxCharsPerLine) {
String[] words = split(inputText, ' ');
ArrayList<string> lines = new ArrayList<string>();
String currentLine = "";
for (String word : words) {
// 尝试添加单词(含前置空格)
String candidate = currentLine + " " + word;
if (candidate.trim().length() >= maxCharsPerLine && !currentLine.isEmpty()) {
lines.add(currentLine.trim());
currentLine = word; // 新行从当前单词开始
} else {
currentLine = candidate;
}
}
// 添加最后一行(避免空行)
if (!currentLine.isEmpty()) lines.add(currentLine.trim());
return lines;
}
}</string></string></string>
⚠️ 注意:该方法以字符数粗略估算换行点,适用于字号固定、字体等宽的场景;生产环境推荐用 textWidth(str) 精确测量。
? 渲染多行居中文本
在 riddle() 函数中调用分段工具,并利用 for 循环逐行绘制:
void riddle() {
fill(0);
textSize(24); // 建议降低字号提升可读性(原50过大)
textAlign(CENTER); // 关键!启用水平居中对齐
textFont(createFont("Arial", 24));
// 计算起始Y:使整体文本块垂直居中
ArrayList<string> lines = TextSplitter.splitText(riddle, 18);
float lineHeight = textAscent() + textDescent() + 6; // 行高 ≈ 字高 + 间隙
float startY = height/2 - ((lines.size() - 1) * lineHeight) / 2;
// 逐行绘制,每行X固定为 width/2,Y动态递增
for (int i = 0; i <h3>✅ 关键要点总结</h3>
<ul>
<li>
<strong>textAlign(CENTER) 必须在 text() 调用前设置</strong>,且作用于后续所有 text() 直到被重置;</li>
<li>
<strong>避免硬编码 textScrPos += 64</strong>:应使用 textAscent() + textDescent() 获取真实字高,再加合理行距(如 +6);</li>
<li>
<strong>整体垂直居中</strong>:通过计算文本块总高度,反推首行 Y 坐标,而非从 0 或固定值开始累加;</li>
<li>
<strong>动态适应新句子</strong>:只要 riddle 字符串更新,splitText() 和循环渲染会自动重新布局,无需手动调整坐标。</li>
</ul>
<h3>? 进阶优化建议</h3>
<ul>
<li>替换字符数限制为 textWidth() 测量,提升不同字体/字号下的鲁棒性;</li>
<li>封装为可复用函数:drawCenteredText(String text, int maxWidth, int fontSize, float x, float y);</li>
<li>支持换行符 \n 和缩进保留,增强富文本兼容性。</li>
</ul>
<p>通过以上结构化实现,你将获得一个真正灵活、可维护的居中文本渲染方案——无论输入“Hello World”还是百字谜题,都能在画布中央清晰、整齐地呈现。</p></string>










