feat: 修改字母描红逻辑,添加字母手写字体

This commit is contained in:
R524809
2026-04-15 17:29:59 +08:00
parent ec5bc44741
commit 4299c4e082
62 changed files with 4135 additions and 894 deletions
@@ -0,0 +1,87 @@
import { BaseDrawService } from '../../../core/draw/baseDraw';
import type { LetterTracingData } from '../generators/letter-tracing-generator';
import { drawFourLineGrid } from './drawTools';
const LETTER_FACE =
'Helvetica, Arial, "Segoe UI", Roboto, sans-serif';
type OverviewData = Extract<LetterTracingData, { mode: 'overview' }>;
export default class OverviewDraw extends BaseDrawService {
async draw(data: OverviewData) {
this.prepareDraw();
await this.drawHeaderAndDivider();
this.drawContent(data.upperRows, data.lowerRows);
this.drawPrintFooter();
}
private drawContent(upperRows: string[][], lowerRows: string[][]) {
const ctx = this.ctx;
const M = 24;
let y = this.currentY + 6;
const innerW = this.canvasWidth - M * 2;
const drawTitle = (t: string) => {
ctx.fillStyle = '#111';
ctx.font = 'bold 17px sans-serif';
ctx.textAlign = 'left';
ctx.textBaseline = 'top';
ctx.fillText(t, M, y);
y += 24;
};
const drawBand = (rows: string[][]) => {
for (const line of rows) {
const n = line.length;
const gap = 4;
const cellW = (innerW - (n - 1) * gap) / n;
const cellH = 30;
for (let i = 0; i < n; i++) {
const cx = M + i * (cellW + gap);
drawFourLineGrid(ctx, cx, y, cellW, cellH);
this.drawCharInCell(
line[i],
cx,
y,
cellW,
cellH,
0.9,
true,
);
}
y += cellH + 8;
}
};
drawTitle('Uppercase Letters');
drawBand(upperRows);
y += 6;
this.drawDashedDivider(y, M, '#bbb');
y += 12;
drawTitle('lowercase Letters');
drawBand(lowerRows);
}
private drawCharInCell(
ch: string,
x: number,
y: number,
w: number,
h: number,
opacity: number,
bold: boolean,
) {
const ctx = this.ctx;
if (opacity <= 0) return;
ctx.save();
ctx.globalAlpha = opacity;
ctx.fillStyle = bold ? '#1a1a1a' : '#4a4a4a';
ctx.textAlign = 'center';
ctx.textBaseline = 'alphabetic';
const baselineY = y + h * 0.72;
const fontSize = Math.min(h * 0.72, w * 0.85);
ctx.font = `${bold ? 'bold ' : ''}${fontSize}px ${LETTER_FACE}`;
ctx.fillText(ch, x + w / 2, baselineY);
ctx.restore();
}
}