feat: 开发完成拼音每日一练
This commit is contained in:
@@ -15,6 +15,18 @@ import {
|
||||
drawLetterInFourLineGrid,
|
||||
loadLetterFont,
|
||||
} from '../../shared/draw/drawTools';
|
||||
import {
|
||||
SECTION_PADDING_TOP,
|
||||
SECTION_PADDING_BOTTOM,
|
||||
HEADER_TITLE_GAP,
|
||||
HEADER_META_GAP,
|
||||
CONTENT_TOP_GAP,
|
||||
FOOTER_PHRASE_GAP,
|
||||
FOOTER_INDEX_GAP,
|
||||
drawSectionHeader,
|
||||
drawSectionFooter,
|
||||
getRandomEncouragementPhrase,
|
||||
} from '../../../core/draw/dailyPracticeDrawHelper';
|
||||
|
||||
type DailyCheckinData = Extract<
|
||||
LetterTracingData,
|
||||
@@ -27,22 +39,6 @@ const PAGE_MARGIN_X = 14;
|
||||
const PAGE_MARGIN_Y = 14;
|
||||
// 每个分区内容区左右内边距(px)
|
||||
const SECTION_PADDING_X = 18;
|
||||
// 每个分区内容区顶部内边距(px)
|
||||
const SECTION_PADDING_TOP = 12;
|
||||
// 每个分区内容区底部内边距(px)
|
||||
const SECTION_PADDING_BOTTOM = 10;
|
||||
|
||||
// 标题与上一元素的垂直间距(px)
|
||||
const HEADER_TITLE_GAP = 32;
|
||||
// 标题与元信息(如日期、学号等)的间距(px)
|
||||
const HEADER_META_GAP = 22;
|
||||
// 正文内容距标题/元信息顶部的间距(px)
|
||||
const CONTENT_TOP_GAP = 14;
|
||||
|
||||
// 页脚短语与内容之间的间距(px)
|
||||
const FOOTER_PHRASE_GAP = 26;
|
||||
// 页脚索引与短语之间的间距(px)
|
||||
const FOOTER_INDEX_GAP = 22;
|
||||
|
||||
// 单个格子区列数
|
||||
const GRID_COLS = 5;
|
||||
@@ -146,70 +142,12 @@ export default class DailyCheckinDraw extends BaseDrawService {
|
||||
) {
|
||||
if (!section) return;
|
||||
|
||||
this.drawSectionHeader(rect);
|
||||
this.drawSectionFooter(rect, section.pageNumber);
|
||||
const phrase = getRandomEncouragementPhrase();
|
||||
drawSectionHeader(this.ctx, rect, '字母每日打卡');
|
||||
drawSectionFooter(this.ctx, rect, phrase, `- ${section.pageNumber} -`);
|
||||
this.drawSectionGrid(rect, section.rows);
|
||||
}
|
||||
|
||||
private drawSectionHeader(rect: {
|
||||
x: number;
|
||||
y: number;
|
||||
w: number;
|
||||
h: number;
|
||||
}) {
|
||||
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;
|
||||
|
||||
this.ctx.save();
|
||||
this.ctx.fillStyle = '#322E25';
|
||||
this.ctx.textAlign = 'center';
|
||||
this.ctx.textBaseline = 'middle';
|
||||
|
||||
this.ctx.font = '20px serif';
|
||||
this.ctx.fillText('每日打卡', cx, titleY);
|
||||
|
||||
this.ctx.font = '12px serif';
|
||||
this.ctx.fillText('月', rect.x + 76, metaY);
|
||||
this.ctx.fillText('日', rect.x + 122, metaY);
|
||||
this.ctx.fillText('姓名:', rect.x + 176, metaY);
|
||||
|
||||
this.ctx.strokeStyle = '#8E897E';
|
||||
this.ctx.lineWidth = 1;
|
||||
this.ctx.setLineDash([]);
|
||||
this.ctx.beginPath();
|
||||
this.ctx.moveTo(rect.x + 40, metaUnderlineY);
|
||||
this.ctx.lineTo(rect.x + 68, metaUnderlineY);
|
||||
this.ctx.moveTo(rect.x + 85, metaUnderlineY);
|
||||
this.ctx.lineTo(rect.x + 113, metaUnderlineY);
|
||||
this.ctx.moveTo(rect.x + 195, metaUnderlineY);
|
||||
this.ctx.lineTo(rect.x + 248, metaUnderlineY);
|
||||
this.ctx.stroke();
|
||||
|
||||
this.ctx.restore();
|
||||
}
|
||||
|
||||
private drawSectionFooter(
|
||||
rect: { x: number; y: number; w: number; h: number },
|
||||
pageNumber: number,
|
||||
) {
|
||||
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;
|
||||
|
||||
this.ctx.save();
|
||||
this.ctx.fillStyle = '#3E3A33';
|
||||
this.ctx.textAlign = 'center';
|
||||
this.ctx.textBaseline = 'middle';
|
||||
this.ctx.font = '14px serif';
|
||||
this.ctx.fillText('日拱一卒 不期而至', cx, phraseY);
|
||||
this.ctx.font = '12px serif';
|
||||
this.ctx.fillText(`- ${pageNumber} -`, cx, indexY);
|
||||
this.ctx.restore();
|
||||
}
|
||||
|
||||
private drawSectionGrid(
|
||||
rect: { x: number; y: number; w: number; h: number },
|
||||
rows: DailyCheckinRow[],
|
||||
|
||||
@@ -85,7 +85,7 @@ export const LETTER_TRACING_WORKSHEET_DEFINITIONS = [
|
||||
{
|
||||
id: 'letter-tracing-daily-checkin',
|
||||
icon: 'task-o',
|
||||
title: '每日打卡',
|
||||
title: '字母每日打卡',
|
||||
subtitle: '四宫格每日字母打卡练习',
|
||||
ageMin: 6,
|
||||
ageMax: 8,
|
||||
@@ -95,7 +95,8 @@ export const LETTER_TRACING_WORKSHEET_DEFINITIONS = [
|
||||
},
|
||||
] as const satisfies ReadonlyArray<LetterTracingWorksheetDefinition>;
|
||||
|
||||
type LetterTracingWorksheetRow = (typeof LETTER_TRACING_WORKSHEET_DEFINITIONS)[number];
|
||||
type LetterTracingWorksheetRow =
|
||||
(typeof LETTER_TRACING_WORKSHEET_DEFINITIONS)[number];
|
||||
|
||||
const LETTER_TRACING_WORKSHEET_BY_ID = Object.fromEntries(
|
||||
LETTER_TRACING_WORKSHEET_DEFINITIONS.map((m) => [m.id, m]),
|
||||
|
||||
Reference in New Issue
Block a user