App Inventor 2 文字转图片教程 - 文图生成方案

« 返回首页

概述

“文图”——将文字内容转换为图片,用于社交媒体分享、海报生成、引用图片等。

方案对比

方案 自由度 中文支持 难度
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 🐝 整理。

文档反馈