feat:2.6.1增加 数物对应 和 根据颜色画图形

This commit is contained in:
R524809
2025-12-23 13:35:19 +08:00
parent 9b6a0a26cc
commit 20496c3cc8
28 changed files with 940 additions and 277 deletions
@@ -0,0 +1,158 @@
/**
* 根据颜色画图形绘制服务
*/
import { BaseDrawService } from '../../../service/baseDraw';
import { drawShapeSymbolShape } from '../shapes/shapeSymbolShapes';
/**
* 根据颜色画图形数据
*/
export interface ColorShapeMatchData {
/** 阅览区域的4组数据 */
legendItems: Array<{
shapeId: string;
color: string;
}>;
/** 练习区域的5x5网格数据 */
practiceGrid: Array<Array<string | null>>; // 存储颜色,null表示空白
}
/**
* 根据颜色画图形绘制服务
*/
class ColorShapeMatchDraw extends BaseDrawService {
gridData: ColorShapeMatchData | null = null;
constructor(
canvas: Canvas,
ctx: RenderingContext,
options?: Record<string, any>,
) {
super(canvas, ctx, options);
}
/**
* 绘制根据颜色画图形内容
*/
async draw(gridData: ColorShapeMatchData) {
if (!gridData || !gridData.legendItems || !gridData.practiceGrid) {
return;
}
this.gridData = gridData;
this.prepareDraw();
await this.drawHeaderAndDivider();
this.drawContent({
ctx: this.ctx,
gridData: this.gridData,
canvasWidth: this.canvasWidth,
startY: this.currentY,
});
}
/**
* 绘制内容区域
*/
private drawContent(params: {
ctx: RenderingContext;
gridData: ColorShapeMatchData;
canvasWidth: number;
startY: number;
}): void {
const { ctx, gridData, canvasWidth } = params;
let { startY } = params;
startY = startY + 25;
const margin = 40; // 左右边距
const groupSpacing = 40; // 组间距
const groupSize = 80; // 每组的大小(图形外框大小)
const dotRadius = 15; // 中间圆点的半径
// 计算阅览区域的总宽度
const totalWidth = groupSize * 4 + groupSpacing * 3; // 4组 + 3个间距
const legendStartX =
margin + (canvasWidth - margin * 2 - totalWidth) / 2; // 居中
const legendStartY = startY;
// 绘制阅览区域的4组
gridData.legendItems.forEach((item, index) => {
const groupX = legendStartX + index * (groupSize + groupSpacing);
const groupY = legendStartY;
const centerX = groupX + groupSize / 2;
const centerY = groupY + groupSize / 2;
// 绘制外部图形(有边框,无填充)
drawShapeSymbolShape(
ctx,
item.shapeId,
centerX,
centerY,
groupSize * 1.1, // 图形大小略小于外框
{
fillColor: null,
strokeColor: '#000',
strokeWidth: 2,
},
);
// 绘制中间的圆点(无边线,有填充)
ctx.beginPath();
ctx.arc(centerX, centerY, dotRadius, 0, Math.PI * 2);
ctx.fillStyle = item.color;
ctx.fill();
});
// 绘制虚线分割线
const dividerY = legendStartY + groupSize + 30;
this.drawDashedDivider(dividerY, margin);
// 绘制练习区域(5行5列)
const practiceStartY = dividerY + 30;
const practiceCols = 5;
const practiceRows = 5;
const practiceCellSize = 100; // 每个格子的宽度
const practiceGridWidth = practiceCellSize * practiceCols;
// 计算练习区域起始X位置(居中)
const practiceStartX =
margin + (canvasWidth - margin * 2 - practiceGridWidth) / 2;
// // 绘制练习区域网格线
// this.drawGridLines(
// practiceStartX,
// practiceStartY,
// practiceCellSize,
// practiceCellSize,
// practiceCols,
// practiceRows,
// );
// 绘制练习区域的圆点
// const dotRadius = 15; // 圆点半径
for (let row = 0; row < practiceRows; row++) {
const practiceRow = gridData.practiceGrid[row];
if (!practiceRow) continue;
const rowY = practiceStartY + row * practiceCellSize;
const cellCenterY = rowY + practiceCellSize / 2;
for (let col = 0; col < practiceCols; col++) {
const color = practiceRow[col];
if (!color) continue;
const colX = practiceStartX + col * practiceCellSize;
const cellCenterX = colX + practiceCellSize / 2;
// 绘制圆点(无边线,有填充)
ctx.beginPath();
ctx.arc(cellCenterX, cellCenterY, dotRadius, 0, Math.PI * 2);
ctx.fillStyle = color;
ctx.fill();
}
}
}
}
export default ColorShapeMatchDraw;