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 }, ); } } }