88 lines
2.7 KiB
TypeScript
88 lines
2.7 KiB
TypeScript
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();
|
|
}
|
|
}
|