feat:架构代码优化

This commit is contained in:
R524809
2025-12-11 13:02:44 +08:00
parent 2c32235568
commit 3c0e2af10d
89 changed files with 2774 additions and 2816 deletions
+42 -134
View File
@@ -1,9 +1,5 @@
import { PAPER_SIZE } from '../constants/colors';
import { BaseDrawService } from './baseDraw';
import { CharacterItem } from '../types/characterType';
import {
drawHeader as drawHeaderCommon,
drawMiniHeader as drawMiniHeaderCommon,
} from './headerDrawService';
/**
* 仅支持 M/L/Z 的简单 SVG 路径解析与绘制
@@ -197,14 +193,14 @@ function drawTianZiGrid({
lineColor = '#e0e0e0',
boldColor = '#cccccc',
}: DrawTianZiGridParams) {
// 外框
// 外框(逻辑像素)
ctx.strokeStyle = boldColor;
ctx.lineWidth = 2;
ctx.lineWidth = 1; // 2/3≈1,逻辑像素
ctx.strokeRect(x - size / 2, y - size / 2, size, size);
// 中线
// 中线(逻辑像素)
ctx.strokeStyle = lineColor;
ctx.lineWidth = 1;
ctx.lineWidth = 1; // 逻辑像素
ctx.beginPath();
// 竖线
ctx.moveTo(x, y - size / 2);
@@ -215,7 +211,7 @@ function drawTianZiGrid({
ctx.stroke();
ctx.closePath();
// 对角线(淡)
// 对角线(淡,逻辑像素
ctx.strokeStyle = '#eeeeee';
ctx.lineWidth = 1;
ctx.beginPath();
@@ -227,40 +223,18 @@ function drawTianZiGrid({
ctx.closePath();
}
class WordDrawService {
headerType: PrintHeader = 'wechat';
canvas: WechatMiniprogram.Canvas;
ctx: RenderingContext;
options: Record<string, any>;
paperSize: PaperSize;
currentX: number;
currentY: number;
class WordDrawService extends BaseDrawService {
constructor(
canvas: Canvas,
ctx: RenderingContext,
options?: Record<string, any>,
) {
options = options || {};
this.canvas = canvas;
this.ctx = ctx;
this.paperSize = 'A4';
this.options = {
appName: '涂鸦丫小程序',
appHint: '识字|识图|练字|打印',
super(canvas, ctx, {
title: '田字格 练 字 贴',
subTitle: '按笔画临摹练习',
...options,
};
this.currentX = 0;
this.currentY = 0;
this.setPrintConfig();
}
setPrintConfig() {
const printConfig = getApp().getPrintConfig();
this.headerType = printConfig.header;
this.options.appName = printConfig.appName;
});
}
/**
@@ -271,12 +245,14 @@ class WordDrawService {
this.clear();
this.setPaper();
// 等待页眉绘制完成,确保 this.currentY 被正确设置
// 绘制Header
if (this.headerType !== 'minimal') {
await this.drawHeader();
} else {
await this.drawMiniHeader();
this.drawMiniHeader();
}
this.drawDivider();
this.drawContentEmpty();
}
@@ -301,60 +277,19 @@ class WordDrawService {
* 清空内容区域(页眉以下的部分)
*/
private clearContentArea() {
const { ctx, canvas } = this;
const { ctx } = this;
const contentStartY = this.currentY;
// 清空页眉以下的所有内容
// 清空页眉以下的所有内容(使用逻辑像素)
ctx.fillStyle = '#fff';
ctx.fillRect(
0,
contentStartY,
canvas.width,
canvas.height - contentStartY,
this.canvasWidth,
this.canvasHeight - contentStartY,
);
}
async drawHeader() {
this.currentX = 80;
this.currentY = 80;
await drawHeaderCommon({
canvas: this.canvas,
ctx: this.ctx,
headerType: this.headerType,
options: {
appName: this.options.appName || '涂鸦丫小程序',
appHint: this.options.appHint || '识字|识图|练字|打印',
title: this.options.title || '田字格 练 字 贴',
subTitle: this.options.subTitle || '按笔画临摹练习',
},
onHeaderDrawn: () => {
// wordDrawService 使用不同的计算方式
const titleY = 80;
const headerHeight = Math.max(titleY + 64 + 48 + 48) + 0; // 64px字体 + 48px间距 + 48px字体 + 20px边距
this.currentY = 80 + headerHeight;
this.drawDivider(this.currentY);
},
});
}
drawMiniHeader() {
drawMiniHeaderCommon({
canvas: this.canvas,
ctx: this.ctx,
options: {
appName: this.options.appName || '涂鸦丫小程序',
title: this.options.title || '田字格 练 字 贴',
},
onHeaderDrawn: () => {
// wordDrawService 使用不同的计算方式
const titleY = 120;
const miniHeaderHeight = titleY + 64 + 20; // 64px字体 + 20px边距
this.currentY = miniHeaderHeight;
this.drawDivider(this.currentY);
},
});
}
/**
* 绘制正文内容:两阶段绘制 - 先绘制空田字格,再绘制练字内容
*/
@@ -368,18 +303,18 @@ class WordDrawService {
* rowGap(行间距)用于田字格竖直方向(每一行田字格之间的间隔)的初始最小值。它防止行与行的田字格上下贴得太紧,增加一定的可视呼吸空间。之后同样会结合剩余空间动态调整为实际间距 actualRowGap。
*/
drawContent(characterData: CharacterItem[] | null) {
const { canvas, ctx } = this;
const { ctx } = this;
// 布局参数
const topGap = 50; // 与页眉分割线的距离
const leftMargin = 120;
const rightMargin = 120;
const bottomMargin = 120;
// 布局参数(逻辑像素,原始尺寸除以3
const topGap = 17; // 50/3≈17
const leftMargin = 40; // 120/3=40
const rightMargin = 40; // 120/3=40
const bottomMargin = 40; // 120/3=40
const contentTop = this.currentY + topGap;
const contentWidth = canvas.width - leftMargin - rightMargin;
const contentHeight = canvas.height - contentTop - bottomMargin;
const contentWidth = this.canvasWidth - leftMargin - rightMargin;
const contentHeight = this.canvasHeight - contentTop - bottomMargin;
const cellSize = 140;
const cellSize = 47; // 140/3≈47
// 统一通过 getMaxGridLayout 获取最大行列数
const { maxRow, maxCol } = this.getMaxGridLayout();
@@ -423,20 +358,18 @@ class WordDrawService {
* 获取当前页面可绘制田字格的最大行数与列数(与绘制使用同一套计算规则)
*/
getMaxGridLayout(): { maxRow: number; maxCol: number } {
const { canvas } = this;
// 布局参数需与 drawContent 保持一致
const topGap = 50;
const leftMargin = 120;
const rightMargin = 120;
const bottomMargin = 120;
// 布局参数需与 drawContent 保持一致(逻辑像素)
const topGap = 17; // 50/3≈17
const leftMargin = 40; // 120/3=40
const rightMargin = 40; // 120/3=40
const bottomMargin = 40; // 120/3=40
const contentTop = this.currentY + topGap;
const contentWidth = canvas.width - leftMargin - rightMargin;
const contentHeight = canvas.height - contentTop - bottomMargin;
const contentWidth = this.canvasWidth - leftMargin - rightMargin;
const contentHeight = this.canvasHeight - contentTop - bottomMargin;
const cellSize = 140;
const minGap = 24;
const rowGap = 36;
const cellSize = 47; // 140/3≈47
const minGap = 8; // 24/3=8
const rowGap = 12; // 36/3=12
const maxCol = Math.max(
1,
@@ -596,7 +529,7 @@ class WordDrawService {
uptoInclusive: strokes.length - 1,
fillStyle: 'rgb(0,0,0)', // 黑色填充
strokeStyle: 'rgb(0,0,0)', // 黑色描边
lineWidth: 4, // 较粗的线条
lineWidth: 1, // 较粗的线条4/3≈1,逻辑像素)
});
}
@@ -631,7 +564,7 @@ class WordDrawService {
// console.log(`练习格 [${rowIndex}, ${columnIndex}] 坐标: (${x}, ${y}), 笔画: ${strokeIndex + 1}/${strokes.length}`);
// 绘制到指定笔画的汉字(色,中等粗细)
// 绘制到指定笔画的汉字(色,中等粗细)
drawStrokes({
ctx,
strokes,
@@ -641,38 +574,13 @@ class WordDrawService {
uptoInclusive: strokeIndex,
fillStyle: '#ccc',
strokeStyle: '#ccc',
lineWidth: 3, // 中等粗细
lineWidth: 1, // 中等粗细3/3=1,逻辑像素)
});
}
drawDivider(linY: number) {
const { canvas, ctx } = this;
ctx.strokeStyle = '#000';
ctx.lineWidth = 2;
ctx.beginPath();
ctx.moveTo(80, linY);
ctx.lineTo(canvas.width - 80, linY);
ctx.stroke();
}
setPaper() {
const { ctx, canvas } = this;
const { pixelRatio: dpr } = wx.getWindowInfo();
let { width, height } = PAPER_SIZE[this.paperSize];
width = width * dpr;
height = height * dpr;
canvas.width = width;
canvas.height = height;
this.clear();
ctx.fillStyle = '#fff';
ctx.fillRect(0, 0, width, height);
}
clear() {
const canvas = this.canvas;
this.ctx.clearRect(0, 0, canvas.width, canvas.height);
// drawDivider 已在基类中实现,此方法保留以保持兼容
drawDivider(linY?: number) {
super.drawDivider();
}
}