diff --git a/.workbuddy/memory/2026-08-14.md b/.workbuddy/memory/2026-08-14.md index 2b9a389..873fe50 100644 --- a/.workbuddy/memory/2026-08-14.md +++ b/.workbuddy/memory/2026-08-14.md @@ -15,10 +15,16 @@ ## 新增:训练完成分享海报(canvas 绘制 + 小程序码) - **现象**:训练完成后点分享,微信默认截取当前页面,因完成弹窗垂直居中,卡片只截到上半部分(绿色星星+"完成!"),大数字和按钮被切掉。 - **方案**:用隐藏 canvas 2d 绘制一张 5:4(500×400 逻辑像素)的专用分享海报,在 `onShareAppMessage` 里作为 `imageUrl` 返回;提前在 `_saveAndShowCompletion` 弹窗数据就绪后生成,避免分享时现场绘制延迟。 -- **海报内容**:浅灰底 + 顶部品牌 + 白色圆角成绩卡 + 绿色渐变星星图标 + 状态文案 + 大数字时长 + 连续打卡(如有)+ 底部"扫码一起打卡"引导 + 右下角小程序二维码。 +- **海报内容(初版)**:浅灰底 + 顶部品牌 + 白色圆角成绩卡 + 绿色渐变星星图标 + 状态文案 + 大数字时长 + 连续打卡(如有)+ 底部"扫码一起打卡"引导 + 右下角小程序二维码。 - **文件改动**: - `pages/timer/timer.wxml`:添加隐藏 `` - `pages/timer/timer.wxss`:`.share-poster-canvas` 移出视口、不响应点击 - `pages/timer/timer.js`:新增 `_drawSharePoster()`、`_formatShareDuration()`;`_saveAndShowCompletion()` 里 setData 后预生成;`onShareAppMessage()` 返回 `imageUrl: this._shareImageUrl`;`onTrainAgain()` 清空旧图防止复用 - `static/share-qr.jpg`:加入用户提供的小程序二维码资源 - **注意**:导出用 jpg quality 0.9、dest 500×400,控制文件在 128KB 以内;二维码路径 `/static/share-qr.jpg` 为相对小程序根目录;若二维码加载失败仍导出无二维码的海报,保证分享入口不灰。 + +## 调整:分享海报(实测反馈) +- **反馈**:① 大数字(分钟数)压住了上方"完成"状态文案;② 顶部小程序名称多余;③ 要删二维码。 +- **根因**:初版状态文案 `y=172`(字号22)、大数字基线 `y=230` 且字号最大 90px,数字顶部≈165 落入状态文案区域(150~172),多位数分钟(如纯分钟 "6"→90px)直接压字。 +- **修复**(仅改 `_drawSharePoster` 布局):删除顶部"平板的支撑"品牌名;删除右下角二维码及依赖它的"扫码一起打卡"引导(连带 `static/share-qr.jpg` 也删,不再引用);重排垂直节奏——卡片放大(42~358)、图标 `circleY=104`、状态文案 `y=184`(24px)、大数字基线 `y=286`(上限84px,顶部≈226,与状态文案下沿 192 间距 34 安全)、连续打卡 `y=332`;导出改为绘制完直接 `canvasToTempFilePath`,无需等图片加载。 +- **结论**:海报现为"成绩卡 + 图标 + 状态 + 大数字 + 连续打卡"的极简版,无品牌名无二维码。 diff --git a/pages/timer/timer.js b/pages/timer/timer.js index 871cbb2..a03f900 100644 --- a/pages/timer/timer.js +++ b/pages/timer/timer.js @@ -1037,30 +1037,23 @@ Page({ ctx.fillStyle = '#F7F8FA' ctx.fillRect(0, 0, W, H) - // --- top brand --- - ctx.fillStyle = '#888888' - ctx.font = 'normal 400 18px sans-serif' - ctx.textAlign = 'center' - ctx.textBaseline = 'alphabetic' - ctx.fillText('平板的支撑', W / 2, 36) - // --- main card shadow --- ctx.save() ctx.fillStyle = 'rgba(0,0,0,0.06)' - roundRect(38, 54, 424, 250, 22) + roundRect(38, 44, 424, 320, 22) ctx.fill() ctx.restore() // --- main card --- ctx.save() ctx.fillStyle = '#FFFFFF' - roundRect(35, 52, 430, 246, 20) + roundRect(35, 42, 430, 316, 20) ctx.fill() ctx.restore() // --- gradient circle icon (same feel as completion-emoji-wrap) --- const circleX = W / 2 - const circleY = 108 + const circleY = 104 const circleR = 40 const grad = ctx.createLinearGradient(circleX - circleR, circleY - circleR, circleX + circleR, circleY + circleR) grad.addColorStop(0, '#4CAF50') @@ -1075,23 +1068,24 @@ Page({ drawStar(circleX, circleY, 20, 8, 5) ctx.fill() - // --- status text --- + // --- status text (kept well above the big number so a multi-digit + // minute count never overlaps it) --- ctx.fillStyle = '#333333' - ctx.font = 'normal 600 22px sans-serif' + ctx.font = 'normal 600 24px sans-serif' ctx.textAlign = 'center' ctx.textBaseline = 'alphabetic' - ctx.fillText(message, W / 2, 172) + ctx.fillText(message, W / 2, 184) // --- big number + unit --- const fmt = this._formatShareDuration(elapsed) const numLen = fmt.num.length - const numSize = numLen <= 2 ? 90 : numLen <= 3 ? 76 : numLen <= 4 ? 60 : 48 + const numSize = numLen <= 2 ? 84 : numLen <= 3 ? 70 : numLen <= 4 ? 56 : 44 ctx.font = `normal 800 ${numSize}px sans-serif` ctx.textAlign = 'right' ctx.textBaseline = 'alphabetic' ctx.fillStyle = primary const numX = W / 2 + 4 - const numY = 230 + const numY = 286 ctx.fillText(fmt.num, numX, numY) ctx.fillStyle = '#666666' @@ -1104,57 +1098,25 @@ Page({ ctx.fillStyle = primary ctx.font = 'normal 500 18px sans-serif' ctx.textAlign = 'center' - ctx.fillText(`连续打卡 ${streak} 天`, W / 2, 272) + ctx.fillText(`连续打卡 ${streak} 天`, W / 2, 332) } - // --- bottom left: CTA text --- - ctx.textAlign = 'left' - ctx.textBaseline = 'alphabetic' - ctx.fillStyle = '#333333' - ctx.font = 'normal 700 22px sans-serif' - ctx.fillText('扫码一起打卡', 48, 338) - - ctx.fillStyle = '#999999' - ctx.font = 'normal 400 15px sans-serif' - ctx.fillText('平板的支撑 · 每天进步一点点', 48, 366) - - // --- bottom right: QR code --- - const qrSize = 88 - const qrX = W - 48 - qrSize - const qrY = 308 - const doExport = () => { - wx.canvasToTempFilePath({ - canvas, - width: W, - height: H, - destWidth: W, - destHeight: H, - fileType: 'jpg', - quality: 0.9, - success: (r) => { - this._shareImageUrl = r.tempFilePath - }, - fail: (err) => { - console.warn('[sharePoster] export failed', err) - } - }) - } - - const img = canvas.createImage() - img.src = '/static/share-qr.jpg' - img.onload = () => { - ctx.save() - ctx.fillStyle = '#FFFFFF' - roundRect(qrX - 6, qrY - 6, qrSize + 12, qrSize + 12, 8) - ctx.fill() - ctx.drawImage(img, qrX, qrY, qrSize, qrSize) - ctx.restore() - doExport() - } - img.onerror = () => { - // 二维码加载失败时仍导出一张无二维码的海报,避免分享按钮失效 - doExport() - } + // --- export (no QR; draw immediately) --- + wx.canvasToTempFilePath({ + canvas, + width: W, + height: H, + destWidth: W, + destHeight: H, + fileType: 'jpg', + quality: 0.9, + success: (r) => { + this._shareImageUrl = r.tempFilePath + }, + fail: (err) => { + console.warn('[sharePoster] export failed', err) + } + }) }) }, diff --git a/static/share-qr.jpg b/static/share-qr.jpg deleted file mode 100644 index 8bc4ceb..0000000 Binary files a/static/share-qr.jpg and /dev/null differ