概述
“文图”——将文字内容转换为图片,用于社交媒体分享、海报生成、引用图片等。
方案对比
| 方案 | 自由度 | 中文支持 | 难度 |
|---|---|---|---|
| Canvas绘制 | ⭐⭐ | 部分字体 | ⭐⭐ |
| WebView + HTML2Canvas | ⭐⭐⭐⭐⭐ | ✅ | ⭐⭐⭐ |
| html2canvas库 | ⭐⭐⭐⭐⭐ | ✅ | ⭐⭐⭐ |
方案一:Canvas绘制文字图片
基本用法
当 按钮_生成.被点击
设 Canvas1.画布宽度 = 800
设 Canvas1.画布高度 = 600
调用 Canvas1.清除()
' 绘制背景
调用 Canvas1.画矩形(0, 0, 800, 600, 黑色)
' 绘制标题文字
设 Canvas1.画笔颜色 = 白色
设 Canvas1.字体大小 = 48
调用 Canvas1.画文字(100, 200, 输入框_标题.文本, 白色)
' 绘制内容
设 Canvas1.字体大小 = 24
调用 Canvas1.画文字(100, 300, 输入框_内容.文本, 浅灰色)
' 保存为图片
设 图片路径 = 调用 Canvas1.保存图片()
标签_状态.文本 = "已保存:" & 图片路径
Canvas绘制的局限
- 不支持自动换行(需手动分行)
- 中文字体有限
- 无法使用自定义字体
- 布局计算复杂
Canvas自动换行
定义 画多行文字(画布, 文本, X, 起始Y, 最大宽度, 行高, 颜色) 返回 结束Y
设 当前Y = 起始Y
设 当前行 = ""
设 i = 1
当 i ≤ 文本长度(文本)
设 测试行 = 当前行 & 文本第i个字符(文本)
设 测试宽度 = 测量文本宽度(测试行) ' 需要扩展或估算
如果 测试宽度 > 最大宽度
调用 画布.画文字(X, 当前Y, 当前行, 颜色)
设 当前行 = 文本第i个字符(文本)
设 当前Y = 当前Y + 行高
否则
设 当前行 = 测试行
设 i = i + 1
' 画最后一行
如果 当前行 ≠ ""
调用 画布.画文字(X, 当前Y, 当前行, 颜色)
设 当前Y = 当前Y + 行高
返回 当前Y
方案二:WebView + HTML(推荐)
使用WebView渲染HTML,然后截图保存。这是最灵活的方案。
HTML模板(text_to_image.html)
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="https://cdnjs.cloudflare.com/ajax/libs/html2canvas/1.4.1/html2canvas.min.js"></script>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body { background: #f5f5f5; display: flex; justify-content: center; }
.card {
width: 360px; padding: 30px; background: white;
border-radius: 12px; box-shadow: 0 2px 12px rgba(0,0,0,0.1);
}
.card.gradient-bg {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
}
.quote-mark { font-size: 60px; line-height: 1; opacity: 0.3; }
.title { font-size: 22px; font-weight: bold; margin: 10px 0; line-height: 1.5; }
.content { font-size: 16px; line-height: 1.8; opacity: 0.85; }
.footer { margin-top: 20px; font-size: 13px; opacity: 0.5; text-align: right; }
.author { font-size: 15px; margin-top: 15px; text-align: right; font-weight: bold; }
.divider { border-top: 1px solid rgba(255,255,255,0.3); margin: 15px 0; }
</style>
</head>
<body>
<div class="card gradient-bg" id="card">
<div class="quote-mark">"</div>
<div class="title" id="title">标题文字</div>
<div class="divider"></div>
<div class="content" id="content">内容文字</div>
<div class="author" id="author">— 作者</div>
<div class="footer" id="footer">来自 AppInventor2</div>
</div>
<script>
setInterval(function() {
var msg = window.AppInventor.getWebViewString();
if (msg && msg !== "") {
try {
var data = JSON.parse(msg);
if (data.type === "update") {
document.getElementById('title').textContent = data.title || '';
document.getElementById('content').textContent = data.content || '';
document.getElementById('author').textContent = data.author ? '— ' + data.author : '';
document.getElementById('footer').textContent = data.footer || '来自 AppInventor2';
if (data.bg === 'dark') {
document.getElementById('card').className = 'card gradient-bg';
} else {
document.getElementById('card').className = 'card';
}
} else if (data.type === "capture") {
html2canvas(document.getElementById('card'), {
scale: 2, useCORS: true, backgroundColor: null
}).then(function(canvas) {
var imgData = canvas.toDataURL('image/png');
window.AppInventor.setWebViewString("IMG:" + imgData);
});
}
} catch(e) {
window.AppInventor.setWebViewString("ERROR:" + e.message);
}
}
}, 100);
</script>
</body>
</html>
App Inventon积木块
当 Screen1.初始化
设 WebView1.主页地址 = "file:///android_asset/text_to_image.html"
当 按钮_预览.被点击
设 JSON = "{""type"":""update"",""title"":""" & 输入框_标题.文本 &
""",""content"":""" & 输入框_内容.文本 &
""",""author"":""" & 输入框_作者.文本 &
""",""bg"":""" & (如果 下拉框_背景.选中项 = "深色" 则 "dark" 否则 "light") & """}"
设 WebView1.WebView字符串 = JSON
当 按钮_生成图片.被点击
设 WebView1.WebView字符串 = "{""type"":""capture""}"
当 WebView1.WebView字符串改变(值)
如果 值 以 "IMG:" 开头
设 Base64数据 = 替换文本(值, "IMG:data:image/png;base64,", "")
' 保存Base64到文件
调用 File1.保存文件(Base64数据, "/sdcard/MyApp/text_image.png")
标签_状态.文本 = "✅ 图片已生成"
否则 如果 值 以 "ERROR:" 开头
标签_状态.文本 = "❌ 生成失败"
实战案例:社交分享卡片
功能
- 输入文字内容
- 选择模板(渐变/简约/暗黑)
- 生成精美图片
- 分享到微信/QQ
设 模板列表 = [
{name: "紫色渐变", bg: "linear-gradient(135deg, #667eea, #764ba2)", text: "white"},
{name: "橙色暖阳", bg: "linear-gradient(135deg, #f093fb, #f5576c)", text: "white"},
{name: "清新绿色", bg: "linear-gradient(135deg, #4facfe, #00f2fe)", text: "white"},
{name: "简约白", bg: "white", text: "#333"}
]
当 模板选择器.选择完成(选择)
设 模板 = 模板列表[选择.选中索引]
' 更新WebView中的CSS
调用 WebView1.运行JavaScript(
"document.getElementById('card').style.background='" & 从字典 模板 获取 "bg" & "';" &
"document.getElementById('card').style.color='" & 从字典 模板 获取 "text" & "';"
)
常见问题
Q1: WebView截图中文显示乱码?
确保HTML文件声明了 <meta charset="UTF-8">。如果使用了特殊字体,需要在CSS中指定支持中文的字体:
font-family: -apple-system, 'PingFang SC', 'Microsoft YaHei', sans-serif;
Q2: html2canvas截图为空白?
- 确保DOM已渲染完成后再截图
- 检查元素是否有高度/宽度
- 使用
useCORS: true解决跨域图片问题
Q3: 生成的图片分辨率不够?
html2canvas的 scale 参数控制分辨率:
html2canvas(element, { scale: 3 }) // 3倍分辨率
总结
| 方案 | 推荐度 | 适用 |
|---|---|---|
| Canvas绘制 | ⭐⭐ | 简单文字 |
| WebView + html2canvas | ⭐⭐⭐⭐⭐ | 精美图片 |
| 纯HTML截图 | ⭐⭐⭐⭐ | 通用 |
版权声明:MIT App Inventor 官方文档采用 CC BY-SA 4.0 授权,本文档由 ai2claw 🐝 整理。
扫码添加客服咨询