一个微信小程序的 8 个版本,我踩了哪些坑
「确实佷难压缩」是一个微信图片压缩小程序。从 v1.0.1 到 v2.0.1,8 个版本迭代,每次以为稳了都会冒出新问题。这篇文章记录每个版本的核心改动和踩过的坑。
扫码体验小程序:

v1.0.1:能用就行
第一个版本只做了一件事:选图片 → 压缩 → 保存。
核心能力: - Canvas 本地压缩,图片不上传服务器 - 基础的 JPG/PNG 格式支持
上线第一天就发现:微信会审核图片内容。纯本地压缩不走微信 API,违规图片直接能保存出去。于是加了 imgSecCheck 云函数,压缩后先过一遍微信内容安全审查。
踩坑:审查是异步的,用户看到红色呼吸灯会本能等待,不知道能不能点保存。后来加了"边审边存"提示。
v1.0.4:压缩算法重写
最初的压缩逻辑很粗暴:直接降 quality。结果发现一个问题——选 20KB 压不出来,选 100KB 能压,选 50KB 也能压,再选 20KB 又能压了。不稳定。
原因:单次 quality 调整无法精确控制输出大小。
重写方案:二分搜索 + 两点采样。 - 先在 quality=0.5 和 quality=0.1 各压一次,得到两个点 - 线性插值估算目标 quality - 最多修正 2 轮,最大 Canvas 调用 4 次
顺便把 UI 改成了深色毛玻璃风格。
v1.0.5:大图压不到目标
5000 万像素的大图,原始数据 150MB。二分搜索在 quality 空间里找,但 quality 再低也就那样——像素数太多了。
修复:大图先等比缩小到 4096px 以内,再走二分搜索。4096 是微信 Canvas 的安全上限,再大就崩。
最低 quality 也从 0.1 降到了 0.05,给极端情况多留余地。
v1.0.6:页面闪白
用户反馈:页面切换时会闪一下白屏。
原因:微信小程序的页面背景默认是白色。深色毛玻璃 UI 在页面切换瞬间,新页面还没渲染完就露出了白色底层。
修复:给所有页面的 JSON 配置补上 navigationBarBackgroundColor 和 backgroundColor,消除视觉断裂。
v1.0.7:进度条 + 自定义裁剪
两个大功能:
压缩进度条:之前压缩时只有一个 loading 动画,用户不知道压到哪了。改成百分比 + 状态文字("压缩中 60%" → "审查中 90%" → "完成")。
自定义裁剪尺寸:用户可以手动输入宽高(如 295×413 一寸照)。加了最小值 30px 的限制——输入太小会弹提示。
v1.0.8:Canvas 2D 升级
微信旧版 Canvas API 性能差,大图操作卡顿。升级到 Canvas 2D(type="2d"),速度提升 2-3 倍。
但升级带来了新坑:
- drawImage 必须用 9 参数形式 (img, 0, 0, img.w, img.h, 0, 0, w, h),不然会截取图片
- canvasToTempFilePath 在 Canvas 2D 下不能传 x/y/width/height,只传 destWidth/destHeight
- 改 canvas 宽高后上下文会重置,必须重新 getContext('2d')
还修了一个 bug:裁剪后输出体积反而变大了。原因是裁剪输出格式没跟随用户选择——选了 PNG 就强制输出 PNG,但 PNG 的 Canvas 重编码体积控制很差。改成跟随格式选择。
v1.0.9:裁剪框大修
这是改动最大的一个版本,问题也最多。
根因:坐标系不一致
裁剪框的四角拖拽在自定义尺寸模式下完全失灵。拖左下角,右下角在动。
真正原因不是判定逻辑,而是坐标系偏移。touch.clientX/Y 是 WebView 坐标,frameX/frameY 是 crop-area 内部坐标。两者差了一个 crop-area 的 left/top 偏移。
修法:在 onReady 用 boundingClientRect 缓存偏移量,触摸时统一减掉。
横图变竖条
16:9 的横构图照片,裁剪框显示成了一个竖条。
原因:之前用高度占满 areaH 来定裁剪框尺寸。横图高度小、宽度大,高度占满意味着宽度溢出被 overflow:hidden 切掉左右,只剩中间一条。
修法:横构图改用宽度上限 areaW*0.96,再反推高度。
其他修复
- 角判定热区从无下限改为 44-64px(触控标准)
- 比例锁定:边界钳制时以宽度为基准驱动高度,不再双向独立钳制把比例搞歪
_ready守卫:图片没加载完就禁止触摸,避免 frame 为 0 误判
踩过的最严重的坑
debug 版在 onTouchStart 里引用了 initImage 作用域的局部变量 imgW。一跑就 ReferenceError: imgW is not defined,所有拖拽全部失效。
教训:console.log 埋点用的变量如果跨作用域,发布前必须删干净。
v2.0.0:对比页全新改版
从"压完就完"变成"压完还能看"。
滑动分割线对比:压缩前后并排,中间一条分割线左右拖动。比之前切换原图/效果图直观得多。竖图横图统一用垂直分割线,不搞两套交互。
一键重新裁剪:对比页不满意?不用返回首页重来。直接点"重新裁剪",弹出预设/自定义/自由裁剪选项,闭环操作。
裁剪输出优化:裁剪不再降画质(quality 保持 0.92),格式标注文案也修正了——之前显示"PNG"但实际输出 JPG,误导用户。
v2.0.1:自定义尺寸修正
用户反馈:指定 632×532 的裁剪尺寸,输出却是约 1000×900。
原因:自定义尺寸输入后,canvasToTempFilePath 的 destWidth/destHeight 没有严格取用户输入值,而是走了默认的缩放逻辑。
修复:自定义尺寸模式下,输出尺寸严格按用户输入值,不做任何缩放。
版本一览
| 版本 | 核心改动 | 踩坑 |
|---|---|---|
| v1.0.1 | 基础压缩 + 内容审查 | 审查异步导致用户困惑 |
| v1.0.4 | 二分搜索压缩算法 | quality 空间不稳定 |
| v1.0.5 | 大图先缩小再压缩 | 5000万像素直接崩 |
| v1.0.6 | 修复页面闪白 | 页面背景色未配置 |
| v1.0.7 | 进度条 + 自定义裁剪 | 最小值限制 |
| v1.0.8 | Canvas 2D 升级 | API 参数差异、格式不跟随 |
| v1.0.9 | 裁剪框全面重写 | 坐标系偏移、横图比例、跨作用域变量 |
| v2.0.0 | 对比重塑 + 重新裁剪闭环 | 分割线交互统一 |
| v2.0.1 | 自定义尺寸精确输出 | destWidth/destHeight 缩放逻辑 |
写在后面
8 个版本,核心功能其实没变——选图、压缩、保存。但每个版本都有"以为修好了其实没有"的时刻。
最有意思的教训是:大部分 bug 不是逻辑错,而是假设错。假设坐标系一致、假设高度占满就行、假设 debug 代码不影响正式版。每一个"假设"都变成了一个线上 bug。
如果你也在做小程序,记住两件事:真机测试不能省,debug 代码发布前必须删。
评论