feat:九九乘法表

This commit is contained in:
R524809
2026-01-16 18:02:16 +08:00
parent 7dd10c7902
commit 9c13b44806
25 changed files with 1388 additions and 13 deletions
@@ -0,0 +1,199 @@
/**
* 九九乘法表绘制服务
*/
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;