136 lines
4.6 KiB
TypeScript
136 lines
4.6 KiB
TypeScript
import { BaseDrawService } from '../../../core/draw/baseDraw';
|
||
import { drawNumberPreview } from './numberPreviewDraw';
|
||
import { drawNumberWriteContent } from './numberWriteDraw';
|
||
|
||
/**
|
||
* 数字涂色绘制服务
|
||
* 组合使用基础绘制服务、预览区域绘制服务和内容区域绘制服务
|
||
*/
|
||
class NumberFindDraw extends BaseDrawService {
|
||
selectedNumber: number;
|
||
functionId: string; // 功能ID,用于判断绘制类型
|
||
|
||
constructor(
|
||
canvas: Canvas,
|
||
ctx: RenderingContext,
|
||
options?: Record<string, any>,
|
||
) {
|
||
super(canvas, ctx, options);
|
||
this.selectedNumber = 0;
|
||
this.functionId = options?.functionId || 'number-find';
|
||
}
|
||
|
||
async draw(selectedNumber: number) {
|
||
if (selectedNumber <= 0 || selectedNumber > 10) {
|
||
return;
|
||
}
|
||
|
||
this.selectedNumber = selectedNumber;
|
||
this.prepareDraw();
|
||
await this.drawHeaderAndDivider();
|
||
|
||
// 绘制预览区域
|
||
await drawNumberPreview({
|
||
canvas: this.canvas,
|
||
ctx: this.ctx,
|
||
selectedNumber: this.selectedNumber,
|
||
canvasWidth: this.canvasWidth,
|
||
startY: this.currentY,
|
||
onDrawn: (currentY) => {
|
||
this.currentY = currentY;
|
||
},
|
||
});
|
||
|
||
// 绘制内容区域(根据 functionId 选择不同的绘制方法)
|
||
this.drawDivider();
|
||
if (this.functionId === 'number-write') {
|
||
// 书写类型:绘制书写行
|
||
drawNumberWriteContent({
|
||
ctx: this.ctx,
|
||
selectedNumber: this.selectedNumber,
|
||
canvasWidth: this.canvasWidth,
|
||
startY: this.currentY,
|
||
});
|
||
} else {
|
||
// 默认类型(number-find):绘制数字涂色内容
|
||
this.drawNumberContent({
|
||
ctx: this.ctx,
|
||
selectedNumber: this.selectedNumber,
|
||
canvasWidth: this.canvasWidth,
|
||
startY: this.currentY,
|
||
});
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 绘制数字涂色内容区域
|
||
*/
|
||
private drawNumberContent(params: {
|
||
ctx: RenderingContext;
|
||
selectedNumber: number;
|
||
canvasWidth: number;
|
||
startY: number;
|
||
}): void {
|
||
const { ctx, selectedNumber, canvasWidth, startY } = params;
|
||
const rows = 6;
|
||
const radius = 26; // 约26.67
|
||
const fontSize = 24; // 24
|
||
|
||
const startYPos = startY + 10 + radius; // 约47.33
|
||
const startX1 = 100 + radius; // 约112.22
|
||
const startX2 = 60 + radius; // 约75.56
|
||
const spaceWidthFirst = (canvasWidth - startX1 * 2) / (5 - 1);
|
||
const spaceWidthSecond = (canvasWidth - startX2 * 2) / (6 - 1);
|
||
const spaceHeight = 18; // 18
|
||
|
||
ctx.moveTo(startX1, startYPos);
|
||
for (let i = 0; i < rows; i++) {
|
||
const cols = i % 2 === 0 ? 5 : 6;
|
||
|
||
for (let j = 0; j < cols; j++) {
|
||
const y = startYPos + i * (spaceHeight + radius * 2);
|
||
const x =
|
||
i % 2 === 0
|
||
? startX1 + j * spaceWidthFirst
|
||
: startX2 + j * spaceWidthSecond;
|
||
|
||
// 随机生成1-10的数字,但确保包含选中的数字
|
||
let number: number;
|
||
if (i === 0 && j === 0) {
|
||
// 第一个位置固定为选中的数字
|
||
number = selectedNumber;
|
||
} else {
|
||
// 其他位置随机,但增加选中数字出现的概率
|
||
const random = Math.random();
|
||
if (random < 0.3) {
|
||
// 30%概率是选中的数字
|
||
number = selectedNumber;
|
||
} else {
|
||
// 70%概率是其他随机数字
|
||
number = Math.floor(Math.random() * 10) + 1;
|
||
}
|
||
}
|
||
|
||
// 绘制圆形背景(线宽除以3)
|
||
ctx.fillStyle = '#fff';
|
||
ctx.strokeStyle = '#000';
|
||
ctx.lineWidth = 1; // 约1.33
|
||
ctx.beginPath();
|
||
ctx.arc(x, y, radius, 0, Math.PI * 2);
|
||
ctx.fill();
|
||
ctx.stroke();
|
||
ctx.closePath();
|
||
|
||
// 绘制数字(字体大小除以3)
|
||
ctx.fillStyle = '#333';
|
||
ctx.font = `bold ${fontSize}px "Microsoft Yahei"`;
|
||
ctx.textBaseline = 'middle';
|
||
ctx.textAlign = 'center';
|
||
ctx.fillText(String(number), x, y, radius * 2);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
export default NumberFindDraw;
|