142 lines
4.7 KiB
TypeScript
142 lines
4.7 KiB
TypeScript
// 每个分区内容区顶部内边距(px)
|
|
export const SECTION_PADDING_TOP = 12;
|
|
// 每个分区内容区底部内边距(px)
|
|
export const SECTION_PADDING_BOTTOM = 10;
|
|
|
|
// 标题与上一元素的垂直间距(px)
|
|
export const HEADER_TITLE_GAP = 32;
|
|
// 标题与元信息(如日期、学号等)的间距(px)
|
|
export const HEADER_META_GAP = 22;
|
|
// 正文内容距标题/元信息顶部的间距(px)
|
|
export const CONTENT_TOP_GAP = 14;
|
|
|
|
// 页脚短语与内容之间的间距(px)
|
|
export const FOOTER_PHRASE_GAP = 26;
|
|
// 页脚索引与短语之间的间距(px)
|
|
export const FOOTER_INDEX_GAP = 22;
|
|
|
|
// 20 条鼓励语词库
|
|
export const ENCOURAGEMENT_PHRASES: ReadonlyArray<string> = [
|
|
'书山有路勤为径',
|
|
'日拱一卒 不期而至',
|
|
'宝剑锋从磨砺出',
|
|
'梅花香自苦寒来',
|
|
'业精于勤荒于嬉',
|
|
'行百里者半九十',
|
|
'锲而不舍金石可镂',
|
|
'读万卷书行万里路',
|
|
'滴水穿石非一日之功',
|
|
'天下无难事只怕有心人',
|
|
'熟能生巧功到自然成',
|
|
'敏而好学不耻下问',
|
|
'学而不思则罔',
|
|
'思而不学则殆',
|
|
'欲速则不达',
|
|
'不积跬步无以至千里',
|
|
'不积小流无以成江海',
|
|
'温故而知新',
|
|
'读书破万卷下笔如有神',
|
|
'千里之行始于足下',
|
|
];
|
|
|
|
/**
|
|
* 随机获取一条鼓励语
|
|
*/
|
|
export function getRandomEncouragementPhrase(): string {
|
|
const idx = Math.floor(Math.random() * ENCOURAGEMENT_PHRASES.length);
|
|
return ENCOURAGEMENT_PHRASES[idx];
|
|
}
|
|
|
|
/**
|
|
* 绘制统一的每日练习每个 Section 中的 Header
|
|
* @param ctx 微信小程序 Canvas 绘制上下文
|
|
* @param rect 目标 Section 的位置与宽高信息
|
|
* @param title 标题文本,如 “每日打卡” 或 “拼音每日一练”
|
|
* @param options.centerMeta 是否将 “月/日/姓名” 元信息行整体水平居中(默认 false,保持原左侧布局)
|
|
*/
|
|
export function drawSectionHeader(
|
|
ctx: RenderingContext,
|
|
rect: { x: number; y: number; w: number; h: number },
|
|
title: string,
|
|
options?: { centerMeta?: boolean },
|
|
): void {
|
|
const cx = rect.x + rect.w / 2;
|
|
const titleY = rect.y + SECTION_PADDING_TOP + 12;
|
|
const metaY = titleY + HEADER_TITLE_GAP;
|
|
const metaUnderlineY = metaY + 5;
|
|
|
|
const canvasCtx = ctx as any;
|
|
|
|
canvasCtx.save();
|
|
canvasCtx.fillStyle = '#322E25';
|
|
canvasCtx.textAlign = 'center';
|
|
canvasCtx.textBaseline = 'middle';
|
|
|
|
// 字体样式与 dailyCheckinDraw.ts 保持一致
|
|
canvasCtx.font = '20px serif';
|
|
canvasCtx.fillText(title, cx, titleY);
|
|
|
|
// 元信息行布局:原始版本以 rect.x 为基准(左侧偏移 40~248,宽 208)
|
|
// 当 centerMeta=true 时,整体水平居中到 rect 中部,仅影响调用方显式开启的场景
|
|
const META_BLOCK_WIDTH = 208;
|
|
const META_BASE_OFFSET = 40;
|
|
const metaLeft = options?.centerMeta
|
|
? rect.x + (rect.w - META_BLOCK_WIDTH) / 2
|
|
: rect.x + META_BASE_OFFSET;
|
|
const offset = (n: number) => metaLeft + (n - META_BASE_OFFSET);
|
|
|
|
canvasCtx.font = '12px serif';
|
|
canvasCtx.fillText('月', offset(76), metaY);
|
|
canvasCtx.fillText('日', offset(122), metaY);
|
|
canvasCtx.fillText('姓名:', offset(176), metaY);
|
|
|
|
canvasCtx.strokeStyle = '#8E897E';
|
|
canvasCtx.lineWidth = 1;
|
|
canvasCtx.setLineDash([]);
|
|
canvasCtx.beginPath();
|
|
canvasCtx.moveTo(offset(40), metaUnderlineY);
|
|
canvasCtx.lineTo(offset(68), metaUnderlineY);
|
|
canvasCtx.moveTo(offset(85), metaUnderlineY);
|
|
canvasCtx.lineTo(offset(113), metaUnderlineY);
|
|
canvasCtx.moveTo(offset(195), metaUnderlineY);
|
|
canvasCtx.lineTo(offset(248), metaUnderlineY);
|
|
canvasCtx.stroke();
|
|
|
|
canvasCtx.restore();
|
|
}
|
|
|
|
/**
|
|
* 绘制统一的每日练习每个 Section 中的 Footer
|
|
* @param ctx 微信小程序 Canvas 绘制上下文
|
|
* @param rect 目标 Section 的位置与宽高信息
|
|
* @param phrase 鼓励语文本
|
|
* @param labelText 页面/天数索引文本,如 “- 1 -” 或 “第 1 天”
|
|
*/
|
|
export function drawSectionFooter(
|
|
ctx: RenderingContext,
|
|
rect: { x: number; y: number; w: number; h: number },
|
|
phrase: string,
|
|
labelText: string,
|
|
): void {
|
|
const cx = rect.x + rect.w / 2;
|
|
const phraseY =
|
|
rect.y + rect.h - SECTION_PADDING_BOTTOM - FOOTER_PHRASE_GAP;
|
|
const indexY = rect.y + rect.h - SECTION_PADDING_BOTTOM - 6;
|
|
|
|
const canvasCtx = ctx as any;
|
|
|
|
canvasCtx.save();
|
|
canvasCtx.fillStyle = '#3E3A33';
|
|
canvasCtx.textAlign = 'center';
|
|
canvasCtx.textBaseline = 'middle';
|
|
|
|
// 字体样式与 dailyCheckinDraw.ts 保持一致
|
|
canvasCtx.font = '14px serif';
|
|
canvasCtx.fillText(phrase, cx, phraseY);
|
|
|
|
canvasCtx.font = '12px serif';
|
|
canvasCtx.fillText(labelText, cx, indexY);
|
|
|
|
canvasCtx.restore();
|
|
}
|