102 lines
2.9 KiB
TypeScript
102 lines
2.9 KiB
TypeScript
import { BaseDrawService } from '../../../core/draw/baseDraw';
|
|
import type {
|
|
LetterTracingData,
|
|
TracingRow,
|
|
} from '../generators/letter-tracing-generator';
|
|
import {
|
|
calcLetterFontSizes,
|
|
drawFourLineGrid,
|
|
drawLetterInFourLineGrid,
|
|
FOUR_LINE_GRID_H,
|
|
TOY_FONT_LETTER,
|
|
type LetterFontSizes,
|
|
} from './drawTools';
|
|
|
|
const LETTER_FACE = `${TOY_FONT_LETTER}, Roboto, sans-serif`;
|
|
const COLOR_BLACK = '#1a1a1a';
|
|
const COLOR_LIGHT_RED = 'rgba(252, 46, 0, 0.3)';
|
|
|
|
type ColumnCompareData = Extract<
|
|
LetterTracingData,
|
|
{ mode: 'column-compare' }
|
|
>;
|
|
|
|
/**
|
|
* 分栏对照绘制:
|
|
* 四线三格横跨整页宽度,字母分左右两侧书写——
|
|
* 左半写大写(repetitions 个),右半写小写(repetitions 个),
|
|
* 每侧第一个字母黑色,后续浅红色。
|
|
*/
|
|
export default class ColumnCompareDraw extends BaseDrawService {
|
|
private letterSizes: LetterFontSizes =
|
|
calcLetterFontSizes(FOUR_LINE_GRID_H);
|
|
|
|
async draw(data: ColumnCompareData) {
|
|
this.prepareDraw();
|
|
await this.drawHeaderAndDivider();
|
|
this.drawContent(data.leftRows, data.rightRows);
|
|
this.drawPrintFooter();
|
|
}
|
|
|
|
private drawContent(leftRows: TracingRow[], rightRows: TracingRow[]) {
|
|
const M = 24;
|
|
const lineW = this.canvasWidth - M * 2;
|
|
const maxR = Math.max(leftRows.length, rightRows.length);
|
|
|
|
const footerReserve = 56;
|
|
const availableH =
|
|
this.canvasHeight - this.currentY - footerReserve - 12;
|
|
const rowGap = Math.max(
|
|
4,
|
|
(availableH - maxR * FOUR_LINE_GRID_H) / (maxR + 1),
|
|
);
|
|
|
|
const y0 = this.currentY + rowGap;
|
|
const halfW = lineW / 2;
|
|
|
|
for (let i = 0; i < maxR; i++) {
|
|
const y = y0 + i * (FOUR_LINE_GRID_H + rowGap);
|
|
|
|
drawFourLineGrid(this.ctx, M, y, lineW, FOUR_LINE_GRID_H);
|
|
|
|
if (i < leftRows.length) {
|
|
this.drawLettersInHalf(leftRows[i], M, y, halfW);
|
|
}
|
|
if (i < rightRows.length) {
|
|
this.drawLettersInHalf(rightRows[i], M + halfW, y, halfW);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 在四线三格的半侧区域内绘制字母。
|
|
* 第一个字母黑色,后续字母浅红色。
|
|
*/
|
|
private drawLettersInHalf(
|
|
row: TracingRow,
|
|
x: number,
|
|
y: number,
|
|
halfW: number,
|
|
) {
|
|
const n = row.cells.length;
|
|
if (n === 0) return;
|
|
|
|
const slotW = halfW / n;
|
|
for (let i = 0; i < n; i++) {
|
|
const cell = row.cells[i];
|
|
const color = i === 0 ? COLOR_BLACK : COLOR_LIGHT_RED;
|
|
const cx = x + slotW * i + slotW / 2;
|
|
|
|
drawLetterInFourLineGrid(
|
|
this.ctx,
|
|
cell.char,
|
|
cx,
|
|
y,
|
|
FOUR_LINE_GRID_H,
|
|
this.letterSizes,
|
|
{ fontFamily: LETTER_FACE, color },
|
|
);
|
|
}
|
|
}
|
|
}
|