feat: 涂色识字完善、找字涂色完成
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import type { DebugPublishMeta } from '../../utils/debugPublish';
|
||||
import { inferGradeFromAge } from '../../utils/debugPublish';
|
||||
import type { TemplateType } from '../../service/drawServiceFactory';
|
||||
import type { TemplateType } from '../shared/draw/drawServiceFactory';
|
||||
|
||||
/** 本地 worksheet 元数据(与云库 `worksheets` 文档 `_id` 对齐) */
|
||||
interface WordColoringWorksheetDefinition {
|
||||
@@ -35,9 +35,9 @@ export const WORD_COLORING_WORKSHEET_DEFINITIONS = [
|
||||
icon: 'search',
|
||||
title: '找字涂色',
|
||||
subtitle: '在字海中找到目标字并涂色',
|
||||
ageMin: 4,
|
||||
ageMax: 7,
|
||||
difficulty: 2,
|
||||
ageMin: 3,
|
||||
ageMax: 6,
|
||||
difficulty: 1,
|
||||
tags: ['识字', '涂色', '找字'],
|
||||
sortOrder: 31,
|
||||
},
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
"debug-publish-tools": "../../components3.0/debug-publish-tools/debug-publish-tools",
|
||||
"share-guide-popup": "../../components/share-guide-popup/share-guide-popup",
|
||||
"toy-icon": "../../toy/icon/icon",
|
||||
"color-picker": "../../components/color-picker/color-picker",
|
||||
"word-picker": "../../components/word-picker/word-picker"
|
||||
"color-picker": "../../components3.0/color-picker/color-picker",
|
||||
"word-picker": "../../components3.0/word-picker/word-picker"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
import { WATER_COLORS } from '../../constants/colors';
|
||||
import { WORDS } from '../../constants/words';
|
||||
import { DrawServiceFactory, type IDrawService } from '../../service/drawServiceFactory';
|
||||
import { WORDS } from '../../core/data/words';
|
||||
import {
|
||||
DrawServiceFactory,
|
||||
type IDrawService,
|
||||
} from '../shared/draw/drawServiceFactory';
|
||||
import { createPage, type CanvasDataState } from '../../base/pageMixin';
|
||||
import { defaultShareConfig } from '../../config/config';
|
||||
import {
|
||||
@@ -12,14 +15,26 @@ import {
|
||||
WORD_COLORING_WORKSHEET_DEFINITIONS,
|
||||
} from './wordColoring.config';
|
||||
import type { DebugPublishMeta } from '../../utils/debugPublish';
|
||||
import { addFavorite, removeFavorite, batchCheckFavorited } from '../../utils/favorites';
|
||||
import {
|
||||
addFavorite,
|
||||
removeFavorite,
|
||||
batchCheckFavorited,
|
||||
} from '../../utils/favorites';
|
||||
|
||||
type CardItem = { color: string; word: string };
|
||||
|
||||
const COLOR_MAP: Record<string, string> = {
|
||||
红: '#FF0000', 蓝: '#0000FF', 绿: '#00FF00', 黄: '#FFFF00',
|
||||
黑: '#000000', 白: '#FFFFFF', 紫: '#800080', 橙: '#FF7F00',
|
||||
粉: '#FF69B4', 棕: '#A52A2A', 灰: '#808080',
|
||||
红: '#FF0000',
|
||||
蓝: '#0000FF',
|
||||
绿: '#00FF00',
|
||||
黄: '#FFFF00',
|
||||
黑: '#000000',
|
||||
白: '#FFFFFF',
|
||||
紫: '#800080',
|
||||
橙: '#FF7F00',
|
||||
粉: '#FF69B4',
|
||||
棕: '#A52A2A',
|
||||
灰: '#808080',
|
||||
};
|
||||
|
||||
const MAX_WORDS = 3;
|
||||
@@ -109,7 +124,13 @@ createPage(
|
||||
canvas: Canvas,
|
||||
ctx: RenderingContext,
|
||||
options?: Record<string, any>,
|
||||
) => DrawServiceFactory.create(templateType, canvas, ctx, options),
|
||||
) =>
|
||||
DrawServiceFactory.create(
|
||||
templateType,
|
||||
canvas,
|
||||
ctx,
|
||||
options,
|
||||
),
|
||||
drawServiceOptions: {
|
||||
title: this.data.pageTitle,
|
||||
},
|
||||
@@ -121,7 +142,7 @@ createPage(
|
||||
});
|
||||
},
|
||||
|
||||
// PLACEHOLDER_TS_PART3
|
||||
// PLACEHOLDER_TS_PART3
|
||||
|
||||
/** 执行 Canvas 绘制 */
|
||||
async drawCanvas() {
|
||||
@@ -183,23 +204,33 @@ createPage(
|
||||
const w = allWords[idx];
|
||||
if (!selected.includes(w)) selected.push(w);
|
||||
}
|
||||
const colors = [...WATER_COLORS.basic12].sort(() => Math.random() - 0.5);
|
||||
const colors = [...WATER_COLORS.basic12].sort(
|
||||
() => Math.random() - 0.5,
|
||||
);
|
||||
const cardList = selected.map((word, i) => ({
|
||||
word,
|
||||
color: COLOR_MAP[word] || colors[i % colors.length].hex,
|
||||
}));
|
||||
const inputValue = selected.join('');
|
||||
this.setData({ cardList, selectedWords: selected, inputValue }, () => {
|
||||
this.drawCanvas();
|
||||
});
|
||||
this.setData(
|
||||
{ cardList, selectedWords: selected, inputValue },
|
||||
() => {
|
||||
this.drawCanvas();
|
||||
},
|
||||
);
|
||||
},
|
||||
|
||||
/** 清空文字卡片 */
|
||||
clearCardList() {
|
||||
this.setData({ cardList: [], selectedWords: [], inputValue: '', hasContent: false });
|
||||
this.setData({
|
||||
cardList: [],
|
||||
selectedWords: [],
|
||||
inputValue: '',
|
||||
hasContent: false,
|
||||
});
|
||||
},
|
||||
|
||||
// PLACEHOLDER_TS_PART4
|
||||
// PLACEHOLDER_TS_PART4
|
||||
|
||||
/** 输入框内容变化:同步 cardList */
|
||||
onInputChange(e: WechatMiniprogram.Input) {
|
||||
@@ -215,7 +246,12 @@ createPage(
|
||||
|
||||
/** 清空输入框及卡片 */
|
||||
onClearInput() {
|
||||
this.setData({ inputValue: '', cardList: [], selectedWords: [], hasContent: false });
|
||||
this.setData({
|
||||
inputValue: '',
|
||||
cardList: [],
|
||||
selectedWords: [],
|
||||
hasContent: false,
|
||||
});
|
||||
if (this.drawService) {
|
||||
this.drawCanvas();
|
||||
}
|
||||
@@ -223,9 +259,15 @@ createPage(
|
||||
|
||||
/** 将输入文本同步为 cardList */
|
||||
syncCardsFromInput(value: string) {
|
||||
const chars = [...new Set(value.split('').filter((c: string) => c.trim()))].slice(0, 6);
|
||||
const oldCardMap = new Map<string, string>(this.data.cardList.map((c: CardItem) => [c.word, c.color]));
|
||||
const allColors = WATER_COLORS.basic12.map((c: { hex: string }) => c.hex);
|
||||
const chars = [
|
||||
...new Set(value.split('').filter((c: string) => c.trim())),
|
||||
].slice(0, 6);
|
||||
const oldCardMap = new Map<string, string>(
|
||||
this.data.cardList.map((c: CardItem) => [c.word, c.color]),
|
||||
);
|
||||
const allColors = WATER_COLORS.basic12.map(
|
||||
(c: { hex: string }) => c.hex,
|
||||
);
|
||||
const usedColors = new Set<string>();
|
||||
|
||||
const cardList = chars.map((char) => {
|
||||
@@ -241,7 +283,9 @@ createPage(
|
||||
}
|
||||
const available = allColors.filter((c) => !usedColors.has(c));
|
||||
const shuffled = [...available].sort(() => Math.random() - 0.5);
|
||||
const color = shuffled[0] || allColors[Math.floor(Math.random() * allColors.length)];
|
||||
const color =
|
||||
shuffled[0] ||
|
||||
allColors[Math.floor(Math.random() * allColors.length)];
|
||||
usedColors.add(color);
|
||||
return { word: char, color };
|
||||
});
|
||||
@@ -256,17 +300,28 @@ createPage(
|
||||
onColorDotTap(e: WechatMiniprogram.TouchEvent) {
|
||||
const key = Number(e.currentTarget.dataset.key);
|
||||
const color = e.currentTarget.dataset.color as string;
|
||||
this.setData({ showColorPopup: true, currentKey: key, currentColor: color });
|
||||
this.setData({
|
||||
showColorPopup: true,
|
||||
currentKey: key,
|
||||
currentColor: color,
|
||||
});
|
||||
},
|
||||
|
||||
/** 分类标签点击:打开弹窗定位到对应分类 */
|
||||
onCategoryTap(e: WechatMiniprogram.TouchEvent) {
|
||||
const categoryId = Number(e.currentTarget.dataset.categoryId);
|
||||
this.setData({ showSelectWordPopup: true, pickerCurrentTab: categoryId });
|
||||
this.setData({
|
||||
showSelectWordPopup: true,
|
||||
pickerCurrentTab: categoryId,
|
||||
});
|
||||
},
|
||||
|
||||
onCloseColorPopup() {
|
||||
this.setData({ showColorPopup: false, currentKey: 0, currentColor: '' });
|
||||
this.setData({
|
||||
showColorPopup: false,
|
||||
currentKey: 0,
|
||||
currentColor: '',
|
||||
});
|
||||
},
|
||||
|
||||
onChangeColor(e: WechatMiniprogram.CustomEvent) {
|
||||
@@ -290,8 +345,12 @@ createPage(
|
||||
|
||||
onChangeWord(e: WechatMiniprogram.CustomEvent) {
|
||||
const selectedWords = e.detail.selectedWords as string[];
|
||||
const oldCardMap = new Map<string, string>(this.data.cardList.map((c: CardItem) => [c.word, c.color]));
|
||||
const allColors = WATER_COLORS.basic12.map((c: { hex: string }) => c.hex);
|
||||
const oldCardMap = new Map<string, string>(
|
||||
this.data.cardList.map((c: CardItem) => [c.word, c.color]),
|
||||
);
|
||||
const allColors = WATER_COLORS.basic12.map(
|
||||
(c: { hex: string }) => c.hex,
|
||||
);
|
||||
const usedColors = new Set<string>();
|
||||
|
||||
const cardList = selectedWords.map((word) => {
|
||||
@@ -307,15 +366,25 @@ createPage(
|
||||
}
|
||||
const available = allColors.filter((c) => !usedColors.has(c));
|
||||
const shuffled = [...available].sort(() => Math.random() - 0.5);
|
||||
const color = shuffled[0] || allColors[Math.floor(Math.random() * allColors.length)];
|
||||
const color =
|
||||
shuffled[0] ||
|
||||
allColors[Math.floor(Math.random() * allColors.length)];
|
||||
usedColors.add(color);
|
||||
return { word, color };
|
||||
});
|
||||
|
||||
const inputValue = selectedWords.join('');
|
||||
this.setData({ showSelectWordPopup: false, cardList, selectedWords, inputValue }, () => {
|
||||
this.drawCanvas();
|
||||
});
|
||||
this.setData(
|
||||
{
|
||||
showSelectWordPopup: false,
|
||||
cardList,
|
||||
selectedWords,
|
||||
inputValue,
|
||||
},
|
||||
() => {
|
||||
this.drawCanvas();
|
||||
},
|
||||
);
|
||||
},
|
||||
|
||||
/** 收藏 */
|
||||
@@ -328,7 +397,10 @@ createPage(
|
||||
if (next) addFavorite(id);
|
||||
else removeFavorite(id);
|
||||
}
|
||||
wx.showToast({ title: next ? '收藏成功' : '已取消收藏', icon: 'none' });
|
||||
wx.showToast({
|
||||
title: next ? '收藏成功' : '已取消收藏',
|
||||
icon: 'none',
|
||||
});
|
||||
},
|
||||
|
||||
async loadFavoritedMap() {
|
||||
|
||||
Reference in New Issue
Block a user