Files
doodle-mini/miniprogram/mathPages/shared/service/missingNumberDraw.ts
T
2026-04-09 17:43:22 +08:00

180 lines
5.1 KiB
TypeScript

/**
* 填上缺少的数字绘制服务
*/
import { BaseDrawService } from '../../../core/draw/baseDraw';
/**
* 填上缺少的数字数据
*/
export interface MissingNumberData {
grids: Array<{
numbers: (number | null)[];
colors: (string | null)[];
}>;
maxNumber: number;
}
/**
* 填上缺少的数字绘制服务
*/
class MissingNumberDraw extends BaseDrawService {
missingNumberData: MissingNumberData | null = null;
constructor(
canvas: Canvas,
ctx: RenderingContext,
options?: Record<string, any>,
) {
super(canvas, ctx, options);
this.missingNumberData = null;
}
/**
* 绘制填上缺少的数字内容
*/
async draw(
missingNumberData: MissingNumberData,
rangeType: string = 'within-10',
) {
if (!missingNumberData || !missingNumberData.grids) {
return;
}
this.missingNumberData = missingNumberData;
this.prepareDraw();
await this.drawHeaderAndDivider();
await this.drawContent({
canvas: this.canvas,
ctx: this.ctx,
missingNumberData: this.missingNumberData,
canvasWidth: this.canvasWidth,
startY: this.currentY,
});
}
/**
* 绘制内容区域
*/
private async drawContent(params: {
canvas: WechatMiniprogram.Canvas;
ctx: RenderingContext;
missingNumberData: MissingNumberData;
canvasWidth: number;
startY: number;
}): Promise<void> {
const { ctx, missingNumberData, canvasWidth, startY } = params;
const { grids, maxNumber } = missingNumberData;
const gridMap = {
10: {
cellSize: 95,
colsPerGrid: 5,
fontSize: 50,
gridSpacing: 40,
},
20: {
cellSize: 80,
colsPerGrid: 5,
fontSize: 40,
gridSpacing: 30,
},
40: {
cellSize: 60,
colsPerGrid: 8,
fontSize: 35,
gridSpacing: 30,
},
50: {
cellSize: 52,
colsPerGrid: 10,
fontSize: 28,
gridSpacing: 40,
},
80: {
cellSize: 60,
colsPerGrid: 8,
fontSize: 30,
gridSpacing: 30,
},
100: {
cellSize: 52,
colsPerGrid: 10,
fontSize: 28,
gridSpacing: 20,
},
120: {
cellSize: 52,
colsPerGrid: 10,
fontSize: 28,
gridSpacing: 20,
},
};
// 计算网格布局参数
const leftMargin = 40;
const rightMargin = 40;
const topMargin = 20;
const config = gridMap[maxNumber as keyof typeof gridMap];
const { cellSize, gridSpacing, colsPerGrid, fontSize } = config;
const gridWidth = colsPerGrid * cellSize;
// 计算网格的起始X位置(居中)
const gridStartX =
leftMargin +
(canvasWidth - leftMargin - rightMargin - gridWidth) / 2;
let currentY = startY + topMargin;
// 绘制每个网格
for (let gridIndex = 0; gridIndex < grids.length; gridIndex++) {
const grid = grids[gridIndex];
const gridX = gridStartX;
// 根据实际数字数量计算需要的行数
const rowsPerGrid = Math.ceil(grid.numbers.length / colsPerGrid);
const gridHeight = rowsPerGrid * cellSize;
const gridY = currentY;
// 绘制每个单元格
for (let index = 0; index < grid.numbers.length; index++) {
const row = Math.floor(index / colsPerGrid);
const col = index % colsPerGrid;
const cellX = gridX + col * cellSize;
const cellY = gridY + row * cellSize;
// 绘制单元格边框
ctx.strokeStyle = '#333';
ctx.lineWidth = 1.5;
ctx.strokeRect(cellX, cellY, cellSize, cellSize);
// 绘制数字或空白
const number = grid.numbers[index];
const color = grid.colors[index];
if (number !== null && color !== null) {
// 绘制数字(带颜色)
ctx.fillStyle = color;
ctx.font = `bold ${fontSize}px "Microsoft Yahei"`;
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
ctx.fillText(
String(number),
cellX + cellSize / 2,
cellY + cellSize / 2,
);
}
// 如果为null,则留空(用户填写)
}
// 更新下一个网格的Y位置
currentY += gridHeight + gridSpacing;
}
}
}
export default MissingNumberDraw;