feat: 开发英语启蒙的入口页

This commit is contained in:
R524809
2026-04-21 15:03:38 +08:00
parent 8c1d7e0657
commit b2f5b203f8
62 changed files with 392 additions and 259 deletions
@@ -3,14 +3,14 @@ import type {
LetterTracingData,
TracingRow,
} from '../generators/letter-tracing-generator';
import { fontFamilyOf } from '../data/fontProfiles';
import { fontFamilyOf } from '../../shared/data/fontProfiles';
import {
calcLetterFontSizes,
drawFourLineGrid,
drawLetterInFourLineGrid,
FOUR_LINE_GRID_H,
type LetterFontSizes,
} from './drawTools';
} from '../../shared/draw/drawTools';
const COLOR_BLACK = '#1a1a1a';
const COLOR_LIGHT_RED = '#FF8E8E';
@@ -18,8 +18,8 @@ export default class LetterTracingDraw extends BaseDrawService {
'letter-tracing-upper-lower': UpperLowerDraw,
'letter-tracing-case-pairing': CasePairingDraw,
'letter-tracing-two-column': TwoColumnDraw,
'letter-tracing-single-line': SingleLineDraw,
'letter-tracing-triple': TripleDraw,
'letter-tracing-half': SingleLineDraw,
'letter-tracing-three': TripleDraw,
}[data.mode];
const delegate = new DrawClass(this.canvas, this.ctx, this.options);
@@ -4,7 +4,7 @@ import type {
LetterTracingData,
HighlightGrid,
} from '../generators/letter-tracing-generator';
import { fontFamilyOf } from '../data/fontProfiles';
import { fontFamilyOf } from '../../shared/data/fontProfiles';
import {
calcLetterFontSizes,
drawFourLineGrid,
@@ -12,7 +12,7 @@ import {
FOUR_LINE_GRID_H,
getLetterFontSize,
type LetterFontSizes,
} from './drawTools';
} from '../../shared/draw/drawTools';
const LINE_INK_ALPHA = 'rgba(50, 46, 37, 1)';
const ACCENT_RED = 'rgba(252, 46, 0, 1)';
@@ -6,7 +6,7 @@ import type {
import {
fontFamilyOf,
PRINT_CLEARLY_DASHED,
} from '../data/fontProfiles';
} from '../../shared/data/fontProfiles';
import {
calcLetterFontSizes,
drawFourLineGrid,
@@ -14,14 +14,14 @@ import {
FOUR_LINE_GRID_H,
loadLetterFont,
type LetterFontSizes,
} from './drawTools';
} from '../../shared/draw/drawTools';
const SLOTS_PER_ROW = 6;
const PAIR_GAP = 25;
type SingleLineData = Extract<
LetterTracingData,
{ mode: 'letter-tracing-single-line' }
{ mode: 'letter-tracing-half' }
>;
/**
@@ -34,8 +34,10 @@ 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);
private dashedSizes: LetterFontSizes = calcLetterFontSizes(
FOUR_LINE_GRID_H,
PRINT_CLEARLY_DASHED,
);
async draw(data: SingleLineData) {
this.prepareDraw();
@@ -4,7 +4,10 @@ import type {
TripleSection,
SingleLineRow,
} from '../generators/letter-tracing-generator';
import { fontFamilyOf, PRINT_CLEARLY_DASHED } from '../data/fontProfiles';
import {
fontFamilyOf,
PRINT_CLEARLY_DASHED,
} from '../../shared/data/fontProfiles';
import {
calcLetterFontSizes,
drawFourLineGrid,
@@ -12,7 +15,7 @@ import {
FOUR_LINE_GRID_H,
loadLetterFont,
type LetterFontSizes,
} from './drawTools';
} from '../../shared/draw/drawTools';
// 每行可容纳的格子数(用于三字母精练模板,一行展示 6 个位置)
const SLOTS_PER_ROW = 6;
@@ -23,7 +26,7 @@ const TRIPLE_ROW_GAP = 10;
// 相邻两个字母区域之间的间距(px),大于 TRIPLE_ROW_GAP
const TRIPLE_SECTION_GAP = 20;
type TripleData = Extract<LetterTracingData, { mode: 'letter-tracing-triple' }>;
type TripleData = Extract<LetterTracingData, { mode: 'letter-tracing-three' }>;
/**
*
@@ -3,14 +3,14 @@ import type {
LetterTracingData,
TracingRow,
} from '../generators/letter-tracing-generator';
import { fontFamilyOf } from '../data/fontProfiles';
import { fontFamilyOf } from '../../shared/data/fontProfiles';
import {
calcLetterFontSizes,
drawFourLineGrid,
drawLetterInFourLineGrid,
FOUR_LINE_GRID_H,
type LetterFontSizes,
} from './drawTools';
} from '../../shared/draw/drawTools';
const COLOR_BLACK = '#1a1a1a';
const COLOR_LIGHT_RED = '#FF8E8E';
@@ -4,7 +4,7 @@ import {
PRINT_CLEARLY_BOLD,
PRINT_CLEARLY_DASHED,
fontFamilyOf,
} from '../data/fontProfiles';
} from '../../shared/data/fontProfiles';
import {
calcLetterFontSizes,
drawFourLineGrid,
@@ -12,7 +12,7 @@ import {
FOUR_LINE_GRID_H,
loadLetterFont,
type LetterFontSizes,
} from './drawTools';
} from '../../shared/draw/drawTools';
type UpperLowerData = Extract<
LetterTracingData,
@@ -1,4 +1,4 @@
import { ALPHABET_BY_LETTER, LETTERS_UPPER } from '../data/alphabet';
import { ALPHABET_BY_LETTER, LETTERS_UPPER } from '../../shared/data/alphabet';
/** 字母描红的布局模式(与产品文档六类练习一致) */
export type LetterTracingMode =
@@ -11,9 +11,9 @@ export type LetterTracingMode =
/** 4 分栏对照:半组字母,左栏大写、右栏小写,每行 4 个 */
| 'letter-tracing-two-column'
/** 5 三字母精练:每页聚焦 3 个字母,每字母 4 行(2 行示范 + 2 行简练) */
| 'letter-tracing-triple'
| 'letter-tracing-three'
/** 6 单字母逐行:每行一个字母,13 字母半表(A–M 或 N–Z) */
| 'letter-tracing-single-line';
| 'letter-tracing-half';
/** 字母大小写模式(部分模式不使用) */
export type LetterCaseMode = 'upper' | 'lower' | 'both';
@@ -111,11 +111,11 @@ export type LetterTracingData =
rightRows: TracingRow[];
}
| {
mode: 'letter-tracing-single-line';
mode: 'letter-tracing-half';
rows: SingleLineRow[];
}
| {
mode: 'letter-tracing-triple';
mode: 'letter-tracing-three';
sections: TripleSection[];
}
| {
@@ -239,8 +239,20 @@ function buildSingleLineCells(L: string): (SingleLineCell | null)[] {
return [
{ upper: L, lower, style: 'solid', color: _COLOR_BLACK, alpha: 1 },
{ upper: L, lower, style: 'solid', color: _COLOR_LIGHT_RED, alpha: 1 },
{ upper: L, lower, style: 'solid', color: _COLOR_LIGHT_RED, alpha: 0.5 },
{ upper: L, lower, style: 'dashed', color: _COLOR_LIGHT_RED, alpha: 0.5 },
{
upper: L,
lower,
style: 'solid',
color: _COLOR_LIGHT_RED,
alpha: 0.5,
},
{
upper: L,
lower,
style: 'dashed',
color: _COLOR_LIGHT_RED,
alpha: 0.5,
},
null,
null,
];
@@ -332,7 +344,7 @@ export function generateLetterTracing(
};
}
if (mode === 'letter-tracing-triple') {
if (mode === 'letter-tracing-three') {
const letters = config.tripleLetters ?? ['A', 'B', 'C'];
const sections: TripleSection[] = letters.map((L) => {
const filledRow: SingleLineRow = {
@@ -348,10 +360,10 @@ export function generateLetterTracing(
rows: [filledRow, filledRow, simpleRow, simpleRow],
};
});
return { mode: 'letter-tracing-triple', sections };
return { mode: 'letter-tracing-three', sections };
}
if (mode === 'letter-tracing-single-line') {
if (mode === 'letter-tracing-half') {
const half =
config.alphabetHalf === 'N-Z'
? LETTERS_UPPER.slice(13)
@@ -362,7 +374,7 @@ export function generateLetterTracing(
cells: buildSingleLineCells(L),
}));
return { mode: 'letter-tracing-single-line', rows };
return { mode: 'letter-tracing-half', rows };
}
// letter-tracing-upper-lower
@@ -1,4 +1,4 @@
import LetterTracingDraw from '../shared/draw/letterTracingDraw';
import LetterTracingDraw from './draw/letterTracingDraw';
import { createPage, type CanvasDataState } from '../../base/pageMixin';
import { defaultShareConfig } from '../../config/config';
import { getWorksheetById } from '../../core/data/worksheets';
@@ -8,7 +8,7 @@ import {
normalizeLetter,
type LetterTracingGeneratorConfig,
type LetterTracingMode,
} from '../shared/generators/letter-tracing-generator';
} from './generators/letter-tracing-generator';
import { LETTERS_UPPER, LETTERS_PAIRS } from '../shared/data/alphabet';
import {
DEFAULT_LETTER_PROFILE,
@@ -45,13 +45,13 @@ const MODES = [
desc: '左 AM、右 NZ 配对描红',
},
{
id: 'letter-tracing-single-line',
id: 'letter-tracing-half',
icon: 'square-half',
label: '13字母半表',
desc: '每行一个字母,13 字母半表',
},
{
id: 'letter-tracing-triple',
id: 'letter-tracing-three',
icon: 'ABC-list',
label: '三字母精练',
desc: '每页聚焦 3 个字母深度书写',
@@ -200,8 +200,8 @@ createPage(
: 'upper';
const needsHalf =
this.data.traceMode === 'letter-tracing-case-pairing' ||
this.data.traceMode === 'letter-tracing-single-line';
const isTriple = this.data.traceMode === 'letter-tracing-triple';
this.data.traceMode === 'letter-tracing-half';
const isTriple = this.data.traceMode === 'letter-tracing-three';
return mergeLetterTracingConfig(base, {
selectedLetter: this.data.selectedLetter,
letterCase,
@@ -306,15 +306,15 @@ createPage(
const showLetterPicker = traceMode === 'letter-tracing-single';
const showCaseToggle =
traceMode === 'letter-tracing-case-pairing' ||
traceMode === 'letter-tracing-single-line';
traceMode === 'letter-tracing-half';
const showNextLetter = traceMode === 'letter-tracing-single';
const showTripleGroupPicker = traceMode === 'letter-tracing-triple';
const showTripleGroupPicker = traceMode === 'letter-tracing-three';
const selectedLetter = options?.preserveLetter
? (this.data.selectedLetter ?? 'A')
: normalizeLetter(merged.selectedLetter ?? '');
const letterCaseLower =
traceMode === 'letter-tracing-case-pairing' ||
traceMode === 'letter-tracing-single-line'
traceMode === 'letter-tracing-half'
? merged.alphabetHalf === 'N-Z'
: traceMode === 'letter-tracing-single'
? merged.letterCase === 'lower'
@@ -0,0 +1,2 @@
1. 字母排序
类似 数字排序 number-sort.png 中的玩法,输出大小写字母,来排序。