Files
doodle-mini/miniprogram/englishPages/letterTracing/draw/tripleDraw.ts
T
2026-04-21 15:03:38 +08:00

126 lines
3.7 KiB
TypeScript

import { BaseDrawService } from '../../../core/draw/baseDraw';
import type {
LetterTracingData,
TripleSection,
SingleLineRow,
} from '../generators/letter-tracing-generator';
import {
fontFamilyOf,
PRINT_CLEARLY_DASHED,
} from '../../shared/data/fontProfiles';
import {
calcLetterFontSizes,
drawFourLineGrid,
drawLetterInFourLineGrid,
FOUR_LINE_GRID_H,
loadLetterFont,
type LetterFontSizes,
} from '../../shared/draw/drawTools';
// 每行可容纳的格子数(用于三字母精练模板,一行展示 6 个位置)
const SLOTS_PER_ROW = 6;
// 大小写字母配对间的间隔(px,字母间距)
const PAIR_GAP = 25;
// 同一字母区域内相邻两行四线三格之间的间距(px)
const TRIPLE_ROW_GAP = 10;
// 相邻两个字母区域之间的间距(px),大于 TRIPLE_ROW_GAP
const TRIPLE_SECTION_GAP = 20;
type TripleData = Extract<LetterTracingData, { mode: 'letter-tracing-three' }>;
/**
* 三字母精练绘制:
* 3 个字母区域,每区域 4 行四线三格。
* 前两行展示完整颜色递进(黑→浅红→半透明浅红→虚线),
* 后两行只展示黑色+浅红色两组,其余空白供用户书写。
* 区域之间间距大于行间距。
*/
export default class TripleDraw extends BaseDrawService {
private letterSizes: LetterFontSizes =
calcLetterFontSizes(FOUR_LINE_GRID_H);
private dashedSizes: LetterFontSizes = calcLetterFontSizes(
FOUR_LINE_GRID_H,
PRINT_CLEARLY_DASHED,
);
async draw(data: TripleData) {
this.prepareDraw();
await Promise.all([
this.drawHeaderAndDivider(),
loadLetterFont(PRINT_CLEARLY_DASHED),
]);
this.drawContent(data.sections);
this.drawPrintFooter();
}
private drawContent(sections: TripleSection[]) {
const M = 24;
const lineW = this.canvasWidth - M * 2;
const slotW = lineW / SLOTS_PER_ROW;
let y = this.currentY + 10;
for (let s = 0; s < sections.length; s++) {
const section = sections[s];
for (let r = 0; r < section.rows.length; r++) {
drawFourLineGrid(this.ctx, M, y, lineW, FOUR_LINE_GRID_H);
this.drawRow(section.rows[r], M, y, slotW);
y += FOUR_LINE_GRID_H;
if (r < section.rows.length - 1) {
y += TRIPLE_ROW_GAP;
}
}
if (s < sections.length - 1) {
y += TRIPLE_SECTION_GAP;
}
}
}
private drawRow(
row: SingleLineRow,
marginX: number,
y: number,
slotW: number,
) {
for (let j = 0; j < row.cells.length; j++) {
const cell = row.cells[j];
if (!cell) continue;
const pairCx = marginX + j * slotW + slotW / 2;
const isDashed = cell.style === 'dashed';
const sizes = isDashed ? this.dashedSizes : this.letterSizes;
const fontFamily = fontFamilyOf(
isDashed ? PRINT_CLEARLY_DASHED : sizes._profile,
);
this.ctx.save();
this.ctx.globalAlpha = cell.alpha;
drawLetterInFourLineGrid(
this.ctx,
cell.upper,
pairCx - PAIR_GAP / 2,
y,
FOUR_LINE_GRID_H,
sizes,
{ fontFamily, color: cell.color },
);
drawLetterInFourLineGrid(
this.ctx,
cell.lower,
pairCx + PAIR_GAP / 2,
y,
FOUR_LINE_GRID_H,
sizes,
{ fontFamily, color: cell.color },
);
this.ctx.restore();
}
}
}