“写个字吧”小程序端已经正式上线,核心功能是把普通文字快速转成带手写感、签名感的图片,适合做签名备注、手写文案、练字参考或者聊天里随手发一张“手写便签”。做这个工具型小程序,最值得说的不是它的界面华丽,而是整个从开发到审核再到发布的流程非常典型:单页面功能、无复杂后台、依赖前端canvas绘制、连着几条权限和分享链路。如果你也打算做一个小工具类小程序,或者正在纠结一个文字生成类功能怎么落地成小程序,这篇文章可以少走不少弯路。下面按我实际的开发顺序,把需求边界、环境准备、绘制逻辑、审核细节和上线后排错一起拆开讲。
1. 先确定“写个字吧”要解决的场景和功能边界
工具型小程序最忌讳的就是功能堆叠。刚开始做“写个字吧”的时候,很容易想加上签名生成、字体切换、背景模板、保存分享、会员解锁一整套功能。但实际做完第一版,我觉得最能跑通的最小闭环应该是:输入文字,生成手写体签名图,保存或分享。先把这三步做顺,再谈扩展。
1.1 它是工具型小程序,不是内容社区
“写个字吧”的产品定位很明确:用户输入一段字,它输出一张可用于保存和分享的文字图片。它不是社交平台,不需要关注关系;也不是编辑器,不需要复杂排版。工具型小程序的核心价值在于“用完即走”,但前提是结果够好、路径够短。
我一般会先把用户流程画成一条直线:
- 打开小程序,看到输入框。
- 输入一段文字,可补充字体、颜色、背景等选项。
- 点生成,展示预览图。
- 保存到相册或者分享给微信好友。
这条线越短,用户流失越少。第一版尤其不要加登录、加会员、加复杂设置项,能少一步就少一步。
1.2 核心功能范围:手写风格生成、签名保存、分享导出
“写个字吧”第一版实际上只做了三个核心动作:
- 文字输入:接收用户输入的一段话,限制合理长度。
- 风格变换:基于预置字体和canvas绘制,把文字变成手写体、签名体。
- 导出保存:生成图片后,提供保存到相册和转发好友两个出口。
这几个动作都是前端能力,不需要自建服务器,不需要数据库,也不涉及太复杂的接口。整体开发成本集中在绘制质量上,因为同样的文字用不同字体、间距、画笔宽度画出来,观感差异非常大。
立项时我给“写个字吧”画了一个边界清单:
| 能力范围 | 第一版是否做 | 原因 |
|---|---|---|
| 手写签名图生成 | 做 | 核心卖点 |
| 字体风格切换 | 做少量 | 预置2到3款字体 |
| 背景模板 | 暂缓 | 会直接影响生成逻辑复杂度 |
| 用户登录 | 不做 | 无后端需求 |
| 会员支付 | 暂缓 | 等留存数据出来再考虑 |
| 社区展示 | 不做 | 工具型产品不需要 |
| 批量生成 | 暂缓 | 首版先把单张质量做稳 |
1.3 技术路线选择:原生、uniapp还是 Taro
小程序端可以用原生微信小程序,也可以用 uniapp、Taro 这类跨端框架。做“写个字吧”时我最后选了 uniapp,主要有几个现实原因:
- 开发语言是 Vue 语法,很多页面逻辑写起来比原生 WXML 方便。
- 可以编译到微信小程序、H5 等平台,后续如果要做 Web 版或安卓版,不至于推倒重来。
- HBuilderX 里可以直接运行到微信开发者工具,调试链路比较短。
但我不建议所有项目都无脑选 uniapp。如果你的项目非常依赖微信原生组件、复杂手势、底层性能,或者团队本身很熟原生,那原生小程序更合适。跨端框架的优势是开发效率,代价是遇到平台差异时需要额外适配。
如果只是做“输入文字、生成图片”这种工具,uniapp 完全可以覆盖;但遇到 canvas 绘制、相册保存、分享传参这些点时,还是要回到底层能力去看兼容性。
注意:跨端框架不等于一次编写、处处完美。真机上的 canvas 绘制、保存相册、导航栏高度这些细节,每个平台都有各自的差异,必须真机验证。
2. 开发上线前的基础条件:账号、框架、真机调试
很多人一上来就写代码,结果到审核阶段才发现类目不对、隐私协议缺失、分享参数错误,返工成本非常高。我这次开发“写个字吧”时,先花半天把账号、工具链和调试链路全部理顺,后面整体很顺畅。
2.1 小程序注册和 AppID
开发微信小程序首先要有小程序账号。个人主体和企业主体都能注册,但审核权限、支付能力、服务类目不一样。
“写个字吧”第一版不做支付,用个人主体就能跑通。如果你后续要接微信支付、会员购买,那就必须用企业主体或个体工商户主体。个人主体不能开通支付类目,这一点要提前想清楚。
注册入口在微信公众平台,流程不复杂,需要的材料主要是邮箱、手机号、身份证信息。注册完成后在“开发管理-开发设置”里找到 AppID,这个字符串后面要用。
我见过不少新手把 AppID 和 AppSecret 混在一起,其实 AppSecret 是服务端用的,小程序前端一般不直接用。前端只需要 AppID,用于开发者工具和真机预览。
2.2 开发框架与 IDE
本次“写个字吧”开发使用了 HBuilderX 作为 uniapp 的编辑编译工具,同时安装了微信开发者工具作为编译目标。开发链路是:
HBuilderX 写代码 -> 运行到微信开发者工具 -> 微信开发者工具预览/调试这里有一个很容易踩的坑:HBuilderX 运行到微信开发者工具时,如果后者没有打开服务端口,会提示“运行失败”或者“调度失败”。需要在微信开发者工具的“设置-安全设置”里把“服务端口”打开。
HBuilderX 本身也需要安装小程序依赖。如果你下载的是精简版,第一次运行到小程序目录时,会提示安装一些基础依赖,按提示处理即可。另外 Node 版本不要太老,建议保持在 LTS 版本附近,避免依赖下载和编译报错。
2.3 真机预览和局域网调试
小程序开发和普通网页开发不一样,很多特性只靠模拟器判断会出错。比如:
- 保存相册需要真实授权环境。
- canvas 绘制真机上可能和模拟器渲染不一致。
- 自定义导航栏的高度适配需要看真机刘海屏状态栏。
- 字体文件加载在真机上更慢,容易出现空白瞬间。
所以“写个字吧”从第一版起,我做每个功能后都会在真机上跑一遍。操作路径是:微信开发者工具里点“预览”,生成二维码后手机扫码打开。
真机调试时最好保持手机和电脑在同一网络,同时电脑端不要关闭开发者工具,否则调试连接会中断。真机调试的限制是:调试模式下性能会比正式版慢一些,数据源如果是本地资源,和正式环境也可能不一致,所以最终发布前还要用“体验版”再验证一轮。
3. 页面与生成逻辑:从文字输入到签名图片
“写个字吧”的核心页面很简单,一个输入区、一个选项区、一个预览区。但真正决定体验的是绘制逻辑、字体加载和图片导出这三部分。
3.1 首页布局和输入约束
首页布局我采用了上下分区:上方是预览画布,下方是输入框和参数选项。这样好处是用户输入时能实时看到结果,符合工具型小程序的直觉。
输入约束上,第一版把单个签名的字数限制在 12 个字以内。原因不是技术不支持更多字,而是超过 12 个字后,单行签名图整体观感会被拉散,自动换行又会破坏签名感。如果你做的是长文案生成,可以放宽到 40 字,然后走多行布局,但那就不是“签名”而是“手写卡片”了。
输入框的maxlength属性直接设置 12,同时在生成逻辑里也做了兜底判断:
let text = inputValue.trim(); if (!text) { uni.showToast({ title: '请输入要生成的文字', icon: 'none' }); return; } if (text.length > 12) { uni.showToast({ title: '最多支持12个字', icon: 'none' }); return; }这里要注意,input组件拿到的是字符串,可能包含空格、换行、emoji。第一版建议把换行符过滤掉,否则 canvas 绘制时会因为无法识别换行而出现异常占位。过滤方式不复杂,正则处理即可。
3.2 手写/签名生成的核心处理思路
“写个字吧”的生成逻辑没有用到服务端,也没有使用大模型,而是通过 canvas 2D 绘制实现。
思路拆解如下:
- 准备字体文件,把字体放在静态目录下,并通过
uni.loadFontFace加载。 - 创建离屏 canvas 或通过
uni.createCanvasContext获取绘制上下文。 - 设置字体、字号、颜色、字间距、画笔起点。
- 逐字绘制,或者直接
fillText绘制整段文本。 - 将 canvas 导出为图片临时路径,再显示到预览区。
关键参数如下:
| 参数 | 作用 | 推荐范围 |
|---|---|---|
| fontSize | 字体大小 | 40-60 |
| fontFamily | 字体路径或名称 | 根据实际字体 |
| letterSpacing | 字间距 | 2-8 |
| color | 文字颜色 | 黑、白、灰为主 |
| canvasWidth | 画布宽度 | 600-750 |
| canvasHeight | 画布高度 | 300-800 |
绘制时需要特别注意绘制顺序:先清空画布,再测量文本宽度,最后才填充文字。如果不测量直接绘制,容易出现文字超出画布边界。
const ctx = uni.createCanvasContext('signCanvas', this); ctx.clearRect(0, 0, canvasWidth, canvasHeight); ctx.setFillStyle('#000000'); ctx.setFontSize(48); ctx.setTextAlign('center'); ctx.setTextBaseline('middle'); ctx.fillText(text, canvasWidth / 2, canvasHeight / 2); ctx.draw(false, () => { uni.canvasToTempFilePath({ canvasId: 'signCanvas', success: (res) => { this.previewImage = res.tempFilePath; } }); });这里有一个实战心得:不要一上来就用draw(true, callback)的异步重绘模式,会出现瞬间闪烁或导出为空。先用draw(false)画完,再导出临时路径,稳定性更高。
3.3 字体加载、图片导出和保存相册
字体是“写个字吧”这类工具的灵魂。程序包有限制,主包不能超过 2MB,一个稍微完整的手写字体文件往往有好几 MB,不能直接放包内。
可以放 OSS、对象存储或 CDN,再通过uni.loadFontFace远程加载。首次加载后会缓存,后续使用体验还可以。但要注意两个问题:
- 加载期间字体不可用,需要这时做回退处理。
- 远程字体地址必须支持 HTTPS,并且要有跨域允许,否则真机可能加载失败。
保存相册的逻辑是:先用uni.canvasToTempFilePath拿到本地缓存路径,再用uni.saveImageToPhotosAlbum保存。这个动作需要用户授权,小程序里会弹出系统授权框,用户点击拒绝后,下次再调用时可能没有任何响应。稳妥做法是:
uni.saveImageToPhotosAlbum({ filePath: this.previewImage, success() { uni.showToast({ title: '已保存到相册', icon: 'success' }); }, fail() { uni.showModal({ title: '提示', content: '需要相册权限才能保存图片,请在设置中开启', confirmText: '去设置', success(res) { if (res.confirm) { uni.openSetting(); } } }); } });记得在 app.json 或 pages.json 里配置相册权限说明,审核时会看你的权限使用目的,不能写“用于保存图片”一句空话,最好写明“用于将生成的手写签名图保存到用户相册”。
3.4 动态标题与导航栏适配
微信小程序里默认导航栏标题可以在pages.json里配置,但有些页面需要动态变化,比如分享签名时想把标题改成“我刚生成了一张签名”。动态设置标题比较简单:
uni.setNavigationBarTitle({ title: '写个字吧 - 签名生成' });这里容易忽略的是:setNavigationBarTitle只在当前页面生命周期内有效,页面卸载后标题会恢复默认。所以在onUnload里如果不做重置,下次进入该页面时标题是默认值,还是延用上一次设置,取决于框架实现。实测 uniapp 编译到微信小程序后,默认不会自动重置,需要自己在onShow里根据页面场景重新设置。
自定义导航栏则更复杂,需要获取状态栏高度和导航栏高度,以适配不同的机型。基础代码可以这样写:
const systemInfo = uni.getSystemInfoSync(); this.statusBarHeight = systemInfo.statusBarHeight; // 状态栏高度 this.navBarHeight = 44; // 微信小程序默认导航栏高度,部分机型需要动态计算真实项目中,如果使用自定义导航栏,建议把标题栏高度设为statusBarHeight + 44,并在页面顶部占位。第一版“写个字吧”用的是默认导航栏,省去了这部分适配,开发进度明显更快。如果你要更好看的视觉,也要先跑通基本功能,再考虑自定义导航栏。
4. 提交审核前必须做的几件事
小程序功能写完了并不代表能立刻上线。微信审核关注的点不仅是功能是否正常,还包括内容安全、类目匹配、隐私合规和用户体验。这一部分我整理成可操作的检查清单。
4.1 类目选择与服务条款
“写个字吧”属于工具类。在微信公众平台设置服务类目时,可以选择“工具-效率”或“工具-信息查询”等方向。不同类目审核要求不同,但工具类整体难度不高。
需要准备的材料包括:
- 小程序名称和简介,不能包含夸大词汇。
- 服务类目选择截图。
- 隐私保护指引,如实填写收集了哪些信息,例如输入的文字内容、保存到相册的交互记录。
- 如果使用字体文件,最好确认字体授权,避免版权风险。
小程序名称方面,“写个字吧”这个名字比较口语化,容易通过也容易被用户记住。如果名称被占用,可以在后面加“签名生成”“手写助手”等后缀做区分。
4.2 支付、会员和分享功能的合规处理
第一版“写个字吧”没有接支付,因此不涉及微信支付 v3 对接。但这里要提前说明:微信支付不是想接就能接的,它对主体性质、类目审核、经营资质都有要求。个人主体无法开通微信支付,想靠“打赏”功能替代也不行,个人小程序暂不支持这种变相支付。
如果后续要跑通商业化,建议按下面的时间线准备:
- 注册企业主体或个体工商户主体。
- 在微信公众平台申请微信支付商户号。
- 如果服务端涉及统一下单、回调,需要对接支付 v3 接口。
- 完成支付权限审核,再在代码里接入支付按钮。
这个流程比小程序本身复杂,我一般会在产品迭代规划里单独留一块时间。
分享功能也要注意:分享出去的页面,用户点开时会重新执行onLoad,如果你希望从分享链接进入后能带上某段文字或某个签名图片参数,必须提前在onLoad里处理参数。参数传递在分享路径里不能太长,最好只携带简短文本或 ID,图片路径不建议直接拼在分享链接里。
4.3 授权弹窗、提示文案和内容安全
工具型小程序最容易因为“强制授权”被审核打回。比如用户第一次打开就弹相册授权,这基本不会过审。敏感操作应当在用户触发“保存图片”时才请求授权,而不是进场就要。
“写个字吧”第一版的处理方式是:
- 生成时不需要任何权限。
- 点击“保存到相册”时,才调用
saveImageToPhotosAlbum。 - 拒绝授权后,用
uni.showModal引导去设置页打开,但不强制。
内容安全方面,虽然“写个字吧”是前端绘制,不存储用户数据,但用户输入的文本可能包含违规词汇。稳妥做法是:生成前对输入文本做一次长度、空字符、非法字符校验;有条件的话接内容安全接口,但因为个人主体没有服务端,第一版我先做了前端常用词过滤和长度限制,后续如果用户量上来再补服务端内容审核。
5. 上线后常见问题排查:从启动页到页面跳转
上线后最怕的不是功能复杂,而是用户手机打开后出现问题。由于小程序运行环境高度依赖微信版本、手机系统和网络,“写个字吧”上线后我重点盯着几个高频问题。
5.1 顶部标题、导航栏高度和页面白屏
上线后用户反馈最多的有三类:
- 部分手机打开后页面白屏。
- 顶部标题在小屏手机上被截断。
- 生成图片后预览区空白。
白屏问题第一怀疑对象是远程字体加载阻塞。如果字体加载失败,上游逻辑报错,页面就可能白屏。解决思路是在页面加载时不阻塞主体流程,字体失败后仍使用系统默认字体,只影响视觉,不影响核心生成。
导航栏高度在小屏机型上确实会出现标题显示不全的情况。如果用的不是自定义导航栏,这个问题基本属于平台默认样式,建议把页面标题设置得短一点,比如“写个字吧”而不是“写个字吧-一个非常好用的手写签名生成工具”。
预览区空白经常不是绘制问题,而是canvasToTempFilePath调用时机太早。每次绘制完成后需要留一个draw回调,确保画布内容已经渲染完成,再导出图片。如果导出后tempFilePath为空,多半是画布没有内容或 canvasId 不匹配。
5.2 输入框被软键盘遮挡,以及页面滚动
移动端小程序里,输入框容易被软键盘顶起或者遮挡,尤其页面底部有“生成按钮”时非常明显。uniapp 中处理方式有很多种:设置adjust-position="true",让页面位置自动调整;也可以监听键盘高度,手动把输入按钮上移。
我这里用了一个更稳的写法:给输入框和生成按钮包在一个内容区里,页面最外层设置为scroll-y,当键盘弹起时,滚动到输入框可见位置。
<view class="page-content"> <input v-model="text" placeholder="请输入要生成的文字" confirm-type="done" cursor-spacing="15" @confirm="generate" /> <button @click="generate">生成签名</button> </view>cursor-spacing是输入光标与键盘之间的距离,设置为 15 到 20 比较合适。也可以利用uni.onKeyboardHeightChange检测键盘高度,动态修改底部按钮的padding-bottom:
uni.onKeyboardHeightChange(res => { this.keyboardHeight = res.height; });这个 API 在部分 Android 机型和 iOS 上表现不一致。实测下来,uniapp 编译到微信小程序后,onKeyboardHeightChange是可用的,但需要做条件判断,避免在非键盘场景下误触发。
5.3 页面跳转、分包和明文 scheme
“写个字吧”页面不算多,目录结构比较简单,所以没有做分包。但如果你的工具后续加入模板库、字体市场、个人中心等模块,一定要按分包处理,否则主包体积很容易超过 2MB。
微信公众平台生成的页面路径可以通过二维码或明文 scheme 拉起。实测中要注意:如果拉起时配置了分包路径,目标页面必须是提前声明的分包页面,否则直接跳转到pages/detail/detail这类主包页面通常没问题,但跳转subpkg/detail/detail时必须确保分包名、页面路径和 app.json 里对应的root完全一致。
一个常见问题是:在微信开发者工具里预览新的分包页面是正常的,但从另一个小程序跳过来时提示“页面不存在”。这种情况优先检查app.json的subPackages配置,其次检查要跳转的小程序是否已在 app.json 的navigateToMiniProgramAppIdList里白名单。小程序 A 跳小程序 B,除了要在 A 的后台配置跳转规则,还要在 B 的后台确认开放关系,否则跳转会被拦截。
5.4 保存图片失败与缓存清理
用户反馈“保存成功,但相册里看不到图片”时,不要急着怀疑代码。先确定是否用了相册权限;再确定图片是否真的导出成功;最后检查手机相册里是不是存在“最近删除”或“未分类”目录。
如果代码里已经提示保存成功但相册没图,常见原因是:保存路径为本地缓存目录,还未同步到系统相册。这时候可以延迟提示,在saveImageToPhotosAlbum的success回调里再显示 toast,不要提前提示。
另一个建议是:保存图片前先显示一次预览图,让用户确认“这就是要保存的内容”,再触发保存。这样即使保存失败,用户也知道问题在授权或系统设置,而不是“小程序坏了”。
6. 后续迭代建议:批量化、模板化和数据观察
“写个字吧”第一版上线后,下一步的方向主要围绕三个部分:模板库、批量生成、数据闭环。
6.1 模板库和批量生成
模板库是文字工具类小程序常见的增长点。用户可以选“正式签名”“可爱手写”“商务落款”等不同模板,每个模板对应不同的字体、字号、背景色和排列方式。对开发来说,模板不是简单的图片文件,最好抽象成 JSON 配置:
{ "templateId": "business_001", "name": "商务落款", "fontSize": 42, "fontFamily": "business_font", "color": "#333333", "backgroundColor": "#FFFFFF", "letterSpacing": 4, "height": 400, "width": 750 }生成页面根据templateId选择不同配置,逻辑不用改很多,新增模板就是加配置和字体资源。
批量生成则要考虑性能问题。第一版“写个字吧”单张生成很快,但如果你要支持“一次生成九张不同字体的签名图”,不能直接同时跑多个 canvas 绘制,容易出现内存占用过高或导出互相覆盖。
我更建议的顺序是:
- 遍历模板列表,每次只渲染一个当前画布。
- 导出当前图片后,把临时路径存入数组。
- 完成后展示九宫格预览。
- 用户按需保存单张,或保存全部。
这里不要用 Promise.all 一次性处理多个 canvas 导出,真机上很容易出现图片白屏或导出为空。
6.2 用户反馈收集和版本迭代
小程序迭代节奏非常快,“写个字吧”上线后我一般关注三个数据指标:
- 用户进入生成页到生成成功的比例。
- 生成成功到保存相册的比例。
- 分享按钮的点击率。
如果第一个比例低,说明输入门槛或生成按钮流程有问题;第二个比例低,说明生成质量不够好,或者保存链路太复杂;第三个比例低,说明分享动机和页面引导不够。
反馈收集不用自己搭后台,可以先在页面上放一个悬浮的“反馈”入口,用户提交后通过客服消息或在线表单收集。也可以在小程序后台的“用户反馈”渠道定期查看。
6.3 小成本维护建议
工具型小程序没有后台也可以长期运行,但不代表可以完全不管。维护“写个字吧”时我会做这几件事:
- 每两周检查一次远程字体资源是否稳定,CDN 是否欠费。
- 关注微信开发者工具里的性能面板,绘制耗时是否随着基础库升级变化。
- 查看小程序后台的错误日志,重点看打开页面失败、canvas 报错、保存图片失败这几类。
- 遇到微信基础库升级时,先在开发者工具里做一次回归,再测真机。
这些维护成本不高,但能避免“用户突然打不开”这种完全被动的局面。小程序生态更新速度快,每次升级都可能带来一些隐性变化,不提前回归就容易出线上问题。
7. 复盘:上线真正的重点不是功能多,而是流程稳
“写个字吧”小程序从开发到上线,给我的最大感受是:工具型小程序能跑通,靠的不是复杂功能,而是每一步都尽量稳。
输入要稳,所以要限制字数和非法字符;绘制要稳,所以要正确处理 canvas 导出时机;保存要稳,所以要做授权失败后的引导;分享要稳,所以路径参数要提前设计好;审核要稳,所以类目、隐私、权限说明都要干净清楚。
如果让我给后来者一个建议,那就是:
先把“输入文字、生成图片、保存到相册、分享好友”这条最小链路做成闭环,不要着急加模板、支付、会员这些外围功能。一个用户能顺畅走通主流程,比十个用户卡在授权和生成异常里更有价值。
“写个字吧”第一版能上线,本身就是这个思路的验证。接下来模板库、批量生成和更丰富的手写字体,都会在这条闭环基础上继续扩展。工具型小程序的想象力,从来不是一次做完的,而是把一个点做到透之后,再慢慢长出更多分支。