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

113 lines
3.3 KiB
TypeScript

import { BaseDrawService } from '../../../core/draw/baseDraw';
import type {
LetterTracingData,
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';
const SLOTS_PER_ROW = 6;
const PAIR_GAP = 25;
type SingleLineData = Extract<
LetterTracingData,
{ mode: 'letter-tracing-half' }
>;
/**
* 单字母逐行绘制:
* 13 行四线三格横跨整页宽度,每行划分为 6 组位置。
* 前 4 组展示大小写字母(Aa),后 2 组空白供用户书写。
* 颜色递进:黑色 → 浅红 → 半透明浅红 → 虚线字体+半透明浅红。
*/
export default class SingleLineDraw extends BaseDrawService {
private letterSizes: LetterFontSizes =
calcLetterFontSizes(FOUR_LINE_GRID_H);
private dashedSizes: LetterFontSizes = calcLetterFontSizes(
FOUR_LINE_GRID_H,
PRINT_CLEARLY_DASHED,
);
async draw(data: SingleLineData) {
this.prepareDraw();
await Promise.all([
this.drawHeaderAndDivider(),
loadLetterFont(PRINT_CLEARLY_DASHED),
]);
this.drawContent(data.rows);
this.drawPrintFooter();
}
private drawContent(rows: SingleLineRow[]) {
const M = 24;
const lineW = this.canvasWidth - M * 2;
const rowCount = rows.length;
const footerReserve = 56;
const availableH =
this.canvasHeight - this.currentY - footerReserve - 12;
const rowGap = Math.max(
4,
(availableH - rowCount * FOUR_LINE_GRID_H) / (rowCount + 1),
);
const y0 = this.currentY + rowGap;
const slotW = lineW / SLOTS_PER_ROW;
for (let i = 0; i < rowCount; i++) {
const y = y0 + i * (FOUR_LINE_GRID_H + rowGap);
drawFourLineGrid(this.ctx, M, y, lineW, FOUR_LINE_GRID_H);
const row = rows[i];
for (let j = 0; j < row.cells.length; j++) {
const cell = row.cells[j];
if (!cell) continue;
const pairCx = M + 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();
}
}
}
}