import NumberObjectMatchDraw from '../shared/service/numberObjectMatchDraw'; import { createMathPage, CanvasDataState, } from '../shared/common/mathPageMixin'; import { NumberObjectMatchData } from '../shared/service/numberObjectMatchDraw'; createMathPage({ canvas: null as Canvas | null, ctx: null as RenderingContext | null, boxHeight: 0, boxWidth: 0, drawService: null as NumberObjectMatchDraw | null, matchData: null as NumberObjectMatchData | null, data: { pageTitle: '数物对应', functionId: '', hasContent: false, showShareDialog: false, showTypeSelector: true, // 控制是否显示类型选择器 currentMode: 'match', // 'match' 连线 或 'fill' 填写 currentModeName: '连线', typeActions: [ { name: '连线', value: 'match' }, { name: '填写', value: 'fill' }, ], } as CanvasDataState & { showTypeSelector: boolean; currentMode: string; currentModeName: string; typeActions: Array<{ name: string; value: string }>; }, onLoad(options: { id?: string; mode?: string }) { const functionId = options.id || 'number-object-match'; this.initPageInfo(functionId, '数物对应'); const isFill = functionId === 'number-object-fill'; const currentMode = options.mode || (isFill ? 'fill' : 'match'); this.setData({ currentMode, currentModeName: currentMode === 'fill' ? '填写' : '连线', typeActions: [ { name: '连线', value: 'match' }, { name: '填写', value: 'fill' }, ], }); }, onReady() { this.initCanvas({ createDrawService: ( canvas: Canvas, ctx: RenderingContext, options?: Record, ) => { return new NumberObjectMatchDraw(canvas, ctx, options); }, drawServiceOptions: {}, onCanvasReady: () => { // 初始随机生成 this.onRandom(); }, }); }, /** * 绘制Canvas内容 */ async drawCanvas() { if (!this.ctx || !this.drawService || !this.matchData) { return; } try { await this.drawService.draw(this.matchData, this.data.currentMode); this.setData({ hasContent: true }); } catch (error) { console.error('绘制失败:', error); this.setData({ hasContent: false }); } }, /** * 随机生成 */ onRandom() { // 从两个目录中随机选择4张不重复的图片 // fruits: 1-22, twelve-animals: 1-12 const fruitsIndices = Array.from({ length: 22 }, (_, i) => i + 1); const animalsIndices = Array.from({ length: 12 }, (_, i) => i + 1); // 合并所有可用的图片索引 const allImages: Array<{ imageIndex: number; folder: 'fruits' | 'twelve-animals'; }> = [ ...fruitsIndices.map((idx) => ({ imageIndex: idx, folder: 'fruits' as const, })), ...animalsIndices.map((idx) => ({ imageIndex: idx, folder: 'twelve-animals' as const, })), ]; // 随机打乱并选择4张不重复的图片 const shuffled = [...allImages].sort(() => Math.random() - 0.5); const selectedImages = shuffled.slice(0, 4); // 生成上面区域的16张图片(4行4列) // 每张图片随机出现,并添加随机偏移 const gridImages: Array<{ imageIndex: number; folder: 'fruits' | 'twelve-animals'; offsetX: number; offsetY: number; }> = []; const maxOffset = 15; // 最大偏移量 for (let i = 0; i < 20; i++) { // 从选中的4张图片中随机选择一张 const randomImage = selectedImages[ Math.floor(Math.random() * selectedImages.length) ]; // 生成随机偏移(-maxOffset 到 maxOffset) const offsetX = (Math.random() - 0.5) * 2 * maxOffset; const offsetY = (Math.random() - 0.5) * 2 * maxOffset; gridImages.push({ ...randomImage, offsetX, offsetY, }); } // 下面区域第一行的4张图片(使用选中的4张图片) const bottomImages = [...selectedImages]; // 计算每个图片在上面区域出现的次数 const imageCountMap = new Map(); gridImages.forEach((item) => { const key = `${item.folder}-${item.imageIndex}`; imageCountMap.set(key, (imageCountMap.get(key) || 0) + 1); }); // 获取每个图片的数量(按 selectedImages 的顺序) const imageCounts = selectedImages.map((img) => { const key = `${img.folder}-${img.imageIndex}`; return imageCountMap.get(key) || 0; }); // 将数量乱序排列 const bottomNumbers = [...imageCounts].sort(() => Math.random() - 0.5); this.matchData = { gridImages, bottomImages, bottomNumbers, }; this.drawCanvas(); }, /** 选择类型 */ onSelectType(event: any) { const { name, value } = event.detail; this.setData({ currentMode: value, currentModeName: name, }); // 重新生成数据 this.onRandom(); }, });