feat: 分栏对照开发,字体缩放、定位调整

This commit is contained in:
R524809
2026-04-16 18:04:57 +08:00
parent 4299c4e082
commit fdb2165dc7
8 changed files with 451 additions and 119 deletions
@@ -2,6 +2,118 @@
* 绘制工具集合(后续可继续扩展其他通用绘制方法)
*/
import {
ACTIVE_FONT_PROFILE,
getLetterMetrics,
type FontProfile,
} from '../data/fontProfiles';
// ── 四线三格统一高度(所有页面共用) ──
export const FOUR_LINE_GRID_H = 43;
// ── 英语字母字体集合 ──
export const TOY_FONT_LETTER = 'ToyLetterFont';
let _fontLoaded = false;
export function loadLetterFont(): Promise<void> {
if (_fontLoaded) return Promise.resolve();
return new Promise((resolve, reject) => {
wx.loadFontFace({
family: TOY_FONT_LETTER,
source: `url("${ACTIVE_FONT_PROFILE.url}")`,
scopes: ['native'],
success: () => {
_fontLoaded = true;
resolve();
},
fail: (err) => {
console.error('loadFontFace failed', err);
reject(err);
},
});
});
}
// ── 向后兼容:LetterFontSizes 类型保留,供外部已有调用使用 ──
export type LetterFontSizes = {
/** 字体配置(新机制) */
_profile: FontProfile;
/** gridH(用于运行时计算) */
_gridH: number;
};
/**
* 根据四线三格总高度,构建 LetterFontSizes。
* 内部持有 FontProfile 引用,按字母查表计算。
*/
export function calcLetterFontSizes(gridH: number): LetterFontSizes {
return {
_profile: ACTIVE_FONT_PROFILE,
_gridH: gridH,
};
}
/** 根据字母和字体配置,计算对应 fontSize */
export function getLetterFontSize(
letter: string,
sizes: LetterFontSizes,
): number {
const metrics = getLetterMetrics(letter, sizes._profile);
return sizes._gridH * metrics.scale;
}
/** 根据字母和字体配置,计算基线 Y 偏移修正(px) */
function getLetterBaselineOffset(
letter: string,
sizes: LetterFontSizes,
): number {
const metrics = getLetterMetrics(letter, sizes._profile);
return sizes._gridH * metrics.baselineOffset;
}
// ── 向后兼容:导出 DESCENDERS 集合 ──
export { DESCENDERS } from '../data/fontProfiles';
/**
* 在四线三格中绘制单个字母(基线固定在 y + 2h/3 + baselineOffset)。
*
* @param cx 字母水平中心
* @param gridY 四线三格顶线 Y
* @param gridH 四线三格总高度
* @param sizes 预计算的字号(由 calcLetterFontSizes 生成)
*/
export function drawLetterInFourLineGrid(
ctx: RenderingContext,
letter: string,
cx: number,
gridY: number,
gridH: number,
sizes: LetterFontSizes,
options?: {
fontFamily?: string;
color?: string;
bold?: boolean;
},
) {
const fontFamily =
options?.fontFamily ?? `${TOY_FONT_LETTER}, Roboto, sans-serif`;
const color = options?.color ?? '#1a1a1a';
const bold = options?.bold ?? false;
const baselineY =
gridY + (gridH * 2) / 3 + getLetterBaselineOffset(letter, sizes);
const fontSize = getLetterFontSize(letter, sizes);
ctx.save();
ctx.font = `${bold ? 'bold ' : ''}${fontSize}px ${fontFamily}`;
ctx.fillStyle = color;
ctx.textAlign = 'center';
ctx.textBaseline = 'alphabetic';
ctx.fillText(letter, cx, baselineY);
ctx.restore();
}
export type FourLineGridStyle = {
/** 顶线/底线颜色 */
ink?: string;
@@ -62,4 +174,3 @@ export function drawFourLineGrid(
ctx.lineTo(x + w, yBot);
ctx.stroke();
}