Files
doodle-mini/miniprogram/mathPages/shared/service/multiplicationTableDraw.ts
T
2026-01-16 18:02:16 +08:00

200 lines
6.0 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* 九九乘法表绘制服务
*/
import { BaseDrawService } from '../../../service/baseDraw';
import { getRandomUniqueNumberColors } from '../../../constants/colors';
/**
* 数字转中文(1-99
*/
function numberToChinese(num: number): string {
const digits = ['', '一', '二', '三', '四', '五', '六', '七', '八', '九'];
const tens = [
'',
'十',
'二十',
'三十',
'四十',
'五十',
'六十',
'七十',
'八十',
'九十',
];
if (num === 0) return '零';
if (num < 10) return digits[num];
if (num === 10) return '十';
if (num < 20) return '十' + digits[num % 10];
if (num % 10 === 0) return tens[Math.floor(num / 10)];
return tens[Math.floor(num / 10)] + digits[num % 10];
}
/**
* 生成九九乘法表汉字口诀
* @param a 第一个乘数
* @param b 第二个乘数
* @param result 结果
*/
function getChineseFormula(a: number, b: number, result: number): string {
const aChinese = numberToChinese(a);
const bChinese = numberToChinese(b);
const resultChinese = numberToChinese(result);
return `${aChinese}${bChinese}${resultChinese}`;
}
/**
* 九九乘法表数据
*/
export interface MultiplicationTableData {
// 不需要额外数据,九九乘法表是固定的
}
/**
* 九九乘法表绘制服务
*/
class MultiplicationTableDraw extends BaseDrawService {
tableData: MultiplicationTableData | null = null;
constructor(
canvas: Canvas,
ctx: RenderingContext,
options?: Record<string, any>,
) {
super(canvas, ctx, options);
this.tableData = null;
}
/**
* 绘制九九乘法表内容
*/
async draw(tableData?: MultiplicationTableData) {
this.tableData = tableData || {};
this.prepareDraw();
await this.drawHeaderAndDivider();
await this.drawContent({
canvas: this.canvas,
ctx: this.ctx,
canvasWidth: this.canvasWidth,
startY: this.currentY,
});
}
/**
* 绘制内容区域
*/
private async drawContent(params: {
canvas: WechatMiniprogram.Canvas;
ctx: RenderingContext;
canvasWidth: number;
startY: number;
}): Promise<void> {
const { ctx, canvasWidth, startY } = params;
// 获取9种颜色(1-9列,每列一种颜色)
const colors = getRandomUniqueNumberColors(9);
// 布局参数
const margin = 30; // 左右边距
const topMargin = 40; // 顶部间距
const sectionSpacing = 40; // 上下两部分之间的间距
const dividerMargin = 20; // 分割线左右边距
// 计算可用宽度
const availableWidth = canvasWidth - margin * 2;
const cellWidth = availableWidth / 9; // 每列宽度
const rowHeight = 26; // 每行高度(减小行高)
const fontSize = 12; // 字体大小(减小字体)
let currentY = startY + topMargin;
// ========== 绘制数字版九九乘法表 ==========
const numberTableStartY = currentY;
// 绘制表格边框和内容
for (let row = 1; row <= 9; row++) {
const rowY = numberTableStartY + (row - 1) * rowHeight;
for (let col = 1; col <= row; col++) {
const colX = margin + (col - 1) * cellWidth;
const color = colors[col - 1];
// 绘制单元格边框
ctx.strokeStyle = '#333';
ctx.lineWidth = 1;
ctx.strokeRect(colX, rowY, cellWidth, rowHeight);
// 生成公式:col x row = result
const result = col * row;
const formula = `${col}×${row}=${result}`;
// 绘制公式(带颜色)
ctx.fillStyle = color;
ctx.font = `bold ${fontSize}px "Microsoft Yahei"`;
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
ctx.fillText(
formula,
colX + cellWidth / 2,
rowY + rowHeight / 2,
);
}
}
// 数字版结束位置
const numberTableEndY = numberTableStartY + 9 * rowHeight;
currentY = numberTableEndY + sectionSpacing;
// ========== 绘制虚线分割线 ==========
this.drawLine(
dividerMargin,
currentY,
canvasWidth - dividerMargin,
currentY,
{
isDashed: true,
dashPattern: [4, 4],
color: '#999',
lineWidth: 1,
},
);
currentY += sectionSpacing;
// ========== 绘制汉字版九九乘法表 ==========
const chineseTableStartY = currentY;
const hzFontSize = 8;
// 绘制表格边框和内容
for (let row = 1; row <= 9; row++) {
const rowY = chineseTableStartY + (row - 1) * rowHeight;
for (let col = 1; col <= row; col++) {
const colX = margin + (col - 1) * cellWidth;
const color = colors[col - 1]; // 使用和数字版相同的颜色
// 绘制单元格边框
ctx.strokeStyle = '#333';
ctx.lineWidth = 1;
ctx.strokeRect(colX, rowY, cellWidth, rowHeight);
// 生成汉字口诀
const result = col * row;
const chineseFormula = getChineseFormula(col, row, result);
// 绘制汉字口诀(带颜色)
ctx.fillStyle = color;
ctx.font = `bold ${hzFontSize}px "Microsoft Yahei"`;
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
ctx.fillText(
chineseFormula,
colX + cellWidth / 2,
rowY + rowHeight / 2,
);
}
}
}
}
export default MultiplicationTableDraw;