feat:2.5.0初始化专注启蒙项目
This commit is contained in:
@@ -7,6 +7,7 @@ import { ALL_5X5_SHAPES } from '../shared/shapes/gridShapes5x5';
|
||||
import { ALL_7X7_SHAPES } from '../shared/shapes/gridShapes7x7';
|
||||
import { ShapeTemplate, GridCell } from '../shared/types/gridTypes';
|
||||
import { GridConfig } from '../shared/types/gridTypes';
|
||||
import { FOCUS_FUNCTION_TYPES } from '../../constants/focusFunctions';
|
||||
|
||||
createFocusPage({
|
||||
canvas: null as Canvas | null,
|
||||
@@ -17,12 +18,13 @@ createFocusPage({
|
||||
gridData: null as GridDrawingData | null,
|
||||
|
||||
data: {
|
||||
pageTitle: '格子仿画',
|
||||
pageTitle: '格子仿画 5×5',
|
||||
functionId: '',
|
||||
hasContent: false,
|
||||
showShareDialog: false,
|
||||
currentMode: '3x3', // '3x3', '5x5', '7x7'
|
||||
currentModeName: '3×3',
|
||||
subTitle: '', // 副标题,从配置中获取
|
||||
typeActions: [
|
||||
{ name: '3×3', value: '3x3' },
|
||||
{ name: '5×5', value: '5x5' },
|
||||
@@ -30,10 +32,30 @@ createFocusPage({
|
||||
],
|
||||
},
|
||||
|
||||
onLoad(options: { id?: string }) {
|
||||
onLoad(options: { id?: string; mode?: string }) {
|
||||
const functionId = options.id || 'grid-drawing';
|
||||
const mode = options.mode || '3x3'; // 从参数中读取 mode,默认为 '3x3'
|
||||
|
||||
// 根据 mode 设置对应的模式名称
|
||||
const modeNameMap: Record<string, string> = {
|
||||
'3x3': '3×3',
|
||||
'5x5': '5×5',
|
||||
'7x7': '7×7',
|
||||
};
|
||||
const currentModeName = modeNameMap[mode] || '3×3';
|
||||
|
||||
// 根据 mode 查找配置,获取 desc 作为 subTitle
|
||||
const configItem = FOCUS_FUNCTION_TYPES.find(
|
||||
(item) => item.mode === mode && item.id?.startsWith('grid-drawing'),
|
||||
);
|
||||
const subTitle = configItem?.desc || '在网格中填充颜色,形成各种形状';
|
||||
|
||||
this.setData({
|
||||
pageTitle: `格子仿画 ${mode}`,
|
||||
functionId,
|
||||
currentMode: mode,
|
||||
currentModeName,
|
||||
subTitle,
|
||||
});
|
||||
this.initPageInfo(functionId, '格子仿画');
|
||||
},
|
||||
@@ -48,7 +70,9 @@ createFocusPage({
|
||||
return new GridDraw(canvas, ctx, options);
|
||||
},
|
||||
drawServiceOptions: {
|
||||
subTitle: '在网格中填充颜色,形成各种形状',
|
||||
title: this.data.pageTitle,
|
||||
subTitle:
|
||||
this.data.subTitle || '在网格中填充颜色,形成各种形状',
|
||||
functionId: this.data.functionId,
|
||||
},
|
||||
onCanvasReady: () => {
|
||||
@@ -67,11 +91,6 @@ createFocusPage({
|
||||
}
|
||||
|
||||
try {
|
||||
// 更新 Header 的 Title
|
||||
if (this.drawService) {
|
||||
this.drawService.options.title = this.data.currentModeName;
|
||||
}
|
||||
|
||||
await this.drawService.draw(this.gridData);
|
||||
this.setData({ hasContent: true });
|
||||
} catch (error) {
|
||||
@@ -129,7 +148,7 @@ createFocusPage({
|
||||
for (let i = 0; i < count; i++) {
|
||||
const shapeIndex = i % availableShapes.length;
|
||||
const shape = availableShapes[shapeIndex];
|
||||
const cells = generateCompletePattern(shape);
|
||||
const cells = generateCompletePattern(shape, config);
|
||||
|
||||
// 生成图案签名
|
||||
const patternSignature = cells
|
||||
@@ -152,7 +171,10 @@ createFocusPage({
|
||||
let found = false;
|
||||
for (let j = 0; j < availableShapes.length; j++) {
|
||||
const nextShape = availableShapes[j];
|
||||
const nextCells = generateCompletePattern(nextShape);
|
||||
const nextCells = generateCompletePattern(
|
||||
nextShape,
|
||||
config,
|
||||
);
|
||||
const nextSignature = nextCells
|
||||
.map((c) => `${c.x},${c.y},${c.color}`)
|
||||
.sort()
|
||||
@@ -205,12 +227,12 @@ createFocusPage({
|
||||
allShapes = ALL_3X3_SHAPES;
|
||||
config = { rows: 3, cols: 3 };
|
||||
groupsPerRow = 2; // 每行2组
|
||||
totalRows = 3; // 总共3行
|
||||
totalRows = 4; // 总共3行
|
||||
} else if (mode === '5x5') {
|
||||
allShapes = ALL_5X5_SHAPES;
|
||||
config = { rows: 5, cols: 5 };
|
||||
groupsPerRow = 2;
|
||||
totalRows = 2; // 5x5可以展示2行
|
||||
totalRows = 4; // 5x5可以展示2行
|
||||
} else {
|
||||
// 7x7
|
||||
allShapes = ALL_7X7_SHAPES;
|
||||
@@ -240,10 +262,30 @@ createFocusPage({
|
||||
/** 选择类型 */
|
||||
onSelectType(event: any) {
|
||||
const { name, value } = event.detail;
|
||||
|
||||
// 根据 mode 查找配置,获取 desc 作为 subTitle
|
||||
const configItem = FOCUS_FUNCTION_TYPES.find(
|
||||
(item) =>
|
||||
item.mode === value && item.id?.startsWith('grid-drawing'),
|
||||
);
|
||||
|
||||
const pageTitle = `格子仿画 ${value}`;
|
||||
const subTitle = configItem?.desc || '在网格中填充颜色,形成各种形状';
|
||||
|
||||
// 更新 pageTitle、currentMode、currentModeName 和 subTitle
|
||||
this.setData({
|
||||
pageTitle,
|
||||
currentMode: value,
|
||||
currentModeName: name,
|
||||
subTitle,
|
||||
});
|
||||
|
||||
// 更新绘制服务的 title 和 subTitle
|
||||
if (this.drawService) {
|
||||
this.drawService.options.title = pageTitle;
|
||||
this.drawService.options.subTitle = subTitle;
|
||||
}
|
||||
|
||||
// 重新生成数据
|
||||
this.onRandom();
|
||||
},
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"navigationBarTitleText": "识别图形,涂一涂",
|
||||
"navigationBarBackgroundColor": "#FFD719",
|
||||
"homeButton": true,
|
||||
"backgroundColor": "#F6F6F6",
|
||||
"enablePullDownRefresh": false,
|
||||
"usingComponents": {
|
||||
"van-divider": "@vant/weapp/divider/index",
|
||||
"van-icon": "@vant/weapp/icon/index",
|
||||
"van-popup": "@vant/weapp/popup/index",
|
||||
"van-dialog": "@vant/weapp/dialog/index",
|
||||
"toy-button": "../../ui/button/button",
|
||||
"shape-card": "../../components/shape-card/shape-card",
|
||||
"shape-picker": "../../components/shape-picker/shape-picker",
|
||||
"color-picker": "../../components/color-picker/color-picker",
|
||||
"share-guide-popup": "../../components/share-guide-popup/share-guide-popup"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
page {
|
||||
background-color: #f6f6f6;
|
||||
}
|
||||
|
||||
.page-container {
|
||||
background-color: #f6f6f6;
|
||||
padding: 0 24rpx;
|
||||
box-sizing: border-box;
|
||||
|
||||
.empty {
|
||||
height: 120rpx;
|
||||
}
|
||||
|
||||
.wrapper {
|
||||
background-color: #fff;
|
||||
border-radius: 20rpx;
|
||||
padding: 36rpx 24rpx;
|
||||
box-shadow: 0 6rpx 8rpx rgba(0, 0, 0, 0.15);
|
||||
margin: 30rpx 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.wrapper-title {
|
||||
font-size: 32rpx;
|
||||
color: #141414;
|
||||
margin-bottom: 36rpx;
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
.btn-area {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
gap: 38rpx;
|
||||
}
|
||||
|
||||
.shape-list {
|
||||
margin: 38rpx 0;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
gap: 38rpx;
|
||||
}
|
||||
|
||||
.shape-list-empty {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 60rpx 40rpx;
|
||||
text-align: center;
|
||||
|
||||
.empty-icon {
|
||||
width: 120rpx;
|
||||
height: 120rpx;
|
||||
background: linear-gradient(135deg, #f0f9ff 0%, #e0f2fe 100%);
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-bottom: 32rpx;
|
||||
box-shadow: 0 4rpx 12rpx rgba(59, 130, 246, 0.15);
|
||||
|
||||
.toy-icon {
|
||||
font-size: 48rpx;
|
||||
color: #3b82f6;
|
||||
}
|
||||
}
|
||||
|
||||
.empty-title {
|
||||
font-size: 32rpx;
|
||||
font-weight: 600;
|
||||
color: #374151;
|
||||
margin-bottom: 16rpx;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.empty-desc {
|
||||
font-size: 26rpx;
|
||||
color: #6b7280;
|
||||
line-height: 1.6;
|
||||
margin-bottom: 32rpx;
|
||||
max-width: 400rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.canvas-wrapper {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
min-height: 400rpx;
|
||||
background: #f8f9fa;
|
||||
border-radius: 12rpx;
|
||||
border: 2rpx dashed #dee2e6;
|
||||
}
|
||||
|
||||
.canvas-content {
|
||||
max-width: 100%;
|
||||
border-radius: 8rpx;
|
||||
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.1);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.bottom-btn-box {
|
||||
position: fixed;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
height: 120rpx;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
background-color: #fff;
|
||||
box-shadow: 0px -3.9rpx 5.2rpx rgba(0, 0, 0, 0.15);
|
||||
padding: 0 24rpx;
|
||||
box-sizing: border-box;
|
||||
border-radius: 16rpx 16rpx 0 0;
|
||||
}
|
||||
@@ -0,0 +1,346 @@
|
||||
import { SHAPES, ShapeCard } from '../../constants/shapes';
|
||||
import { WATER_COLORS, PAPER_SIZE } from '../../constants/colors';
|
||||
import ShapeDrawService from '../../service/shapeDrawService';
|
||||
import { checkAndSaveImage } from '../../utils/saveImage';
|
||||
import { shouldShowShareGuide } from '../../utils/shareGuide';
|
||||
import tracker from '../../utils/tracker';
|
||||
|
||||
Page({
|
||||
canvas: null as Canvas | null,
|
||||
ctx: null as RenderingContext | null,
|
||||
boxHeight: 0,
|
||||
boxWidth: 0,
|
||||
shapeDrawService: null as ShapeDrawService | null,
|
||||
timer: null as any,
|
||||
|
||||
data: {
|
||||
shapeList: [] as ShapeCard[],
|
||||
showSelectShapePopup: false,
|
||||
selectedShapeIndex: -1,
|
||||
showColorPopup: false,
|
||||
currentIndex: 0,
|
||||
currentColor: '',
|
||||
isPCDevtool: false,
|
||||
showShareDialog: false, // 显示分享引导弹窗
|
||||
},
|
||||
|
||||
onLoad() {
|
||||
// 判断是否在PC端开发工具上运行
|
||||
// const systemInfo = wx.getDeviceInfo();
|
||||
// if (systemInfo.platform === 'devtools') {
|
||||
// this.setData({
|
||||
// isPCDevtool: true,
|
||||
// });
|
||||
// }
|
||||
|
||||
this.refreshShapeCard();
|
||||
},
|
||||
|
||||
onReady() {
|
||||
const query = wx.createSelectorQuery();
|
||||
query
|
||||
.select('#canvasWrapper')
|
||||
.boundingClientRect((rect) => {
|
||||
if (rect) {
|
||||
const { width, height } = PAPER_SIZE['A4'];
|
||||
const boxWidth = rect.width;
|
||||
const boxHeight = boxWidth / (width / height);
|
||||
|
||||
this.boxHeight = boxHeight;
|
||||
this.boxWidth = boxWidth;
|
||||
|
||||
this.initCanvas(boxWidth, boxHeight);
|
||||
}
|
||||
})
|
||||
.exec();
|
||||
},
|
||||
|
||||
initCanvas(boxWidth: number, boxHeight: number) {
|
||||
wx.createSelectorQuery()
|
||||
.select('#canvasContent')
|
||||
.fields({
|
||||
node: true,
|
||||
size: true,
|
||||
})
|
||||
.exec((res) => {
|
||||
if (res[0] && res[0].node) {
|
||||
const canvas = res[0].node;
|
||||
const ctx = canvas.getContext('2d');
|
||||
if (ctx) {
|
||||
this.canvas = canvas;
|
||||
this.ctx = ctx;
|
||||
// const rect = res[0];
|
||||
this.shapeDrawService = new ShapeDrawService(
|
||||
canvas,
|
||||
ctx,
|
||||
);
|
||||
// shapeDrawService.draw();
|
||||
|
||||
this.setData({ boxWidth, boxHeight });
|
||||
this.drawCanvas();
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
/** 变更shapeList 并更新canvas */
|
||||
drawCanvas(
|
||||
updatedShapeList?: ShapeCard[],
|
||||
callback: () => void = () => {},
|
||||
) {
|
||||
if (updatedShapeList) {
|
||||
this.setData({ shapeList: updatedShapeList }, () => {
|
||||
this.shapeDrawService?.draw(updatedShapeList!);
|
||||
callback();
|
||||
});
|
||||
} else {
|
||||
const shapeList = this.data.shapeList;
|
||||
this.shapeDrawService?.draw(shapeList);
|
||||
}
|
||||
},
|
||||
|
||||
handleSelectShape() {
|
||||
this.setData({
|
||||
showSelectShapePopup: true,
|
||||
selectedShapeIndex: -1,
|
||||
});
|
||||
},
|
||||
|
||||
openSelectShapePopup(e: any) {
|
||||
const { index } = e.detail;
|
||||
this.setData({
|
||||
showSelectShapePopup: true,
|
||||
selectedShapeIndex: index,
|
||||
});
|
||||
},
|
||||
|
||||
closeSelectShapePopup() {
|
||||
this.setData({
|
||||
showSelectShapePopup: false,
|
||||
});
|
||||
},
|
||||
|
||||
onChangeShape(e: any) {
|
||||
const { shapes, singleMode, selectedShapeIndex } = e.detail;
|
||||
const prevShapeList: ShapeCard[] = this.data.shapeList || [];
|
||||
|
||||
let newShapeList: ShapeCard[] = [];
|
||||
|
||||
if (singleMode) {
|
||||
// 单选模式,只替换 selectedShapeIndex 对应的 shape,其他 shape 保持不变和原有颜色
|
||||
newShapeList = prevShapeList.map((item, idx) => {
|
||||
if (idx === selectedShapeIndex) {
|
||||
// 替换为新选中的 shape,保留原有 fillColor
|
||||
return {
|
||||
...shapes[0],
|
||||
fillColor: item.fillColor,
|
||||
};
|
||||
} else {
|
||||
// 其他 shape 不变
|
||||
return item;
|
||||
}
|
||||
});
|
||||
} else {
|
||||
// 多选模式,原有逻辑
|
||||
// 获取所有可用颜色
|
||||
const colorList = WATER_COLORS.basic12.map((item) => item.hex);
|
||||
|
||||
// 记录已被使用的颜色(只考虑当前 shapeList 中的 fillColor)
|
||||
const usedColors = prevShapeList
|
||||
.map((item) => item.fillColor)
|
||||
.filter(Boolean);
|
||||
|
||||
// 记录已分配的颜色,避免重复
|
||||
const assignedColors = [...usedColors];
|
||||
|
||||
// 先将 shapes 转为 Map,方便查找
|
||||
const prevShapeMap = new Map(
|
||||
prevShapeList.map((item) => [item.id, item]),
|
||||
);
|
||||
|
||||
// 随机打乱剩余可用颜色
|
||||
function shuffle(arr: string[]) {
|
||||
for (let i = arr.length - 1; i > 0; i--) {
|
||||
const j = Math.floor(Math.random() * (i + 1));
|
||||
[arr[i], arr[j]] = [arr[j], arr[i]];
|
||||
}
|
||||
return arr;
|
||||
}
|
||||
|
||||
// 计算未被占用的颜色
|
||||
let availableColors = colorList.filter(
|
||||
(color) => !assignedColors.includes(color),
|
||||
);
|
||||
availableColors = shuffle(availableColors);
|
||||
|
||||
shapes.forEach((item: ShapeCard) => {
|
||||
if (prevShapeMap.has(item.id)) {
|
||||
// 已存在,保留原有 fillColor
|
||||
newShapeList.push({
|
||||
...item,
|
||||
fillColor: prevShapeMap.get(item.id)!.fillColor,
|
||||
});
|
||||
} else {
|
||||
// 新增,分配未被占用的颜色
|
||||
const color = availableColors.shift() || colorList[0];
|
||||
assignedColors.push(color);
|
||||
newShapeList.push({
|
||||
...item,
|
||||
fillColor: color,
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 先关闭弹窗
|
||||
this.setData(
|
||||
{
|
||||
showSelectShapePopup: false,
|
||||
shapeList: newShapeList,
|
||||
},
|
||||
() => {
|
||||
this.drawCanvas();
|
||||
},
|
||||
);
|
||||
},
|
||||
/**
|
||||
* 随机生成6个图形
|
||||
*/
|
||||
refreshShapeCard() {
|
||||
// 随机取6个图形
|
||||
const shapesCopy = [...SHAPES];
|
||||
for (let i = shapesCopy.length - 1; i > 0; i--) {
|
||||
const j = Math.floor(Math.random() * (i + 1));
|
||||
[shapesCopy[i], shapesCopy[j]] = [shapesCopy[j], shapesCopy[i]];
|
||||
}
|
||||
const selectedShapes = shapesCopy.slice(0, 6);
|
||||
|
||||
// 随机取6个颜色
|
||||
const colorList = WATER_COLORS.basic12.map((item) => item.hex);
|
||||
const colorsCopy = [...colorList];
|
||||
for (let i = colorsCopy.length - 1; i > 0; i--) {
|
||||
const j = Math.floor(Math.random() * (i + 1));
|
||||
[colorsCopy[i], colorsCopy[j]] = [colorsCopy[j], colorsCopy[i]];
|
||||
}
|
||||
const selectedColors = colorsCopy.slice(0, 6);
|
||||
|
||||
// 分配颜色到图形
|
||||
const shapeList = selectedShapes.map((shape, idx) => ({
|
||||
...shape,
|
||||
fillColor: selectedColors[idx],
|
||||
}));
|
||||
|
||||
// 更新数据
|
||||
this.setData(
|
||||
{
|
||||
shapeList,
|
||||
},
|
||||
() => {
|
||||
// 绘制canvas
|
||||
this.drawCanvas();
|
||||
},
|
||||
);
|
||||
},
|
||||
onDelete(e: any) {
|
||||
const { index } = e.detail;
|
||||
const newShapeList = this.data.shapeList.filter((_, i) => i !== index);
|
||||
this.setData(
|
||||
{
|
||||
shapeList: newShapeList,
|
||||
},
|
||||
() => {
|
||||
// 绘制canvas
|
||||
this.drawCanvas();
|
||||
},
|
||||
);
|
||||
},
|
||||
onColorTap(e: any) {
|
||||
const { index, fillColor } = e.detail;
|
||||
this.setData({
|
||||
showColorPopup: true,
|
||||
currentColor: fillColor,
|
||||
selectedShapeIndex: index,
|
||||
});
|
||||
},
|
||||
onCloseColorPopup() {
|
||||
this.setData({
|
||||
showColorPopup: false,
|
||||
currentColor: '',
|
||||
selectedShapeIndex: 0,
|
||||
});
|
||||
},
|
||||
onChangeColor(e: any) {
|
||||
const { color } = e.detail;
|
||||
const { selectedShapeIndex } = this.data;
|
||||
|
||||
this.setData(
|
||||
{
|
||||
showColorPopup: false,
|
||||
[`shapeList[${selectedShapeIndex}].fillColor`]: color,
|
||||
},
|
||||
() => {
|
||||
// 绘制canvas
|
||||
this.drawCanvas();
|
||||
},
|
||||
);
|
||||
},
|
||||
|
||||
/** 下载打印 */
|
||||
exportToPrint() {
|
||||
if (!this.canvas || this.data.shapeList.length <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 检查是否需要显示分享引导
|
||||
if (shouldShowShareGuide()) {
|
||||
this.setData({ showShareDialog: true });
|
||||
return;
|
||||
}
|
||||
|
||||
// 上报下载埋点
|
||||
tracker.reportDownload('图形涂色');
|
||||
|
||||
// 直接下载
|
||||
checkAndSaveImage(this.canvas);
|
||||
},
|
||||
|
||||
/** 关闭分享引导弹窗 */
|
||||
onCloseShareDialog() {
|
||||
this.setData({ showShareDialog: false });
|
||||
},
|
||||
|
||||
onShareAppMessage() {
|
||||
// 上报分享埋点
|
||||
tracker.reportShare('图形涂色');
|
||||
|
||||
return {
|
||||
title: '涂鸦丫-涂色|识字|图形|打印',
|
||||
path: '/pages/shape/index',
|
||||
imageUrl:
|
||||
'https://cdn.joeyone.cn/doodle/share-img/index-share-v2.png',
|
||||
};
|
||||
},
|
||||
onShareTimeline() {
|
||||
// 上报分享埋点
|
||||
tracker.reportShare('图形涂色');
|
||||
|
||||
return {
|
||||
title: '涂鸦丫-涂色|识字|图形|打印',
|
||||
query: '/pages/shape/index',
|
||||
imageUrl:
|
||||
'https://cdn.joeyone.cn/doodle/share-img/index-share-v2.png',
|
||||
};
|
||||
},
|
||||
|
||||
/** 分享成功回调(由组件触发) */
|
||||
onShareSuccess() {
|
||||
// 只关闭弹窗,不触发下载
|
||||
this.setData({ showShareDialog: false });
|
||||
},
|
||||
|
||||
onUnload() {
|
||||
if (this.timer) {
|
||||
clearTimeout(this.timer);
|
||||
}
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,97 @@
|
||||
<view class="page-container">
|
||||
<view class="wrapper">
|
||||
<text class="wrapper-title">识别图形,涂一涂</text>
|
||||
<view class="btn-area">
|
||||
<toy-button
|
||||
type="green"
|
||||
bind:click="handleSelectShape"
|
||||
width="100%">
|
||||
选择图形
|
||||
</toy-button>
|
||||
<toy-button
|
||||
type="primary"
|
||||
bind:click="refreshShapeCard"
|
||||
width="100%"
|
||||
icon="refresh"
|
||||
icon-class-prefix="toy-icon">
|
||||
随机生成
|
||||
</toy-button>
|
||||
</view>
|
||||
<view class="shape-list" wx:if="{{shapeList.length > 0}}">
|
||||
<shape-card
|
||||
wx:for="{{ shapeList }}"
|
||||
wx:for-item="item"
|
||||
wx:for-index="index"
|
||||
wx:key="{{index}}"
|
||||
index="{{index}}"
|
||||
svg="{{ item.svg }}"
|
||||
fillColor="{{ item.fillColor }}"
|
||||
bind:onShapeTap="openSelectShapePopup"
|
||||
bind:onDelete="onDelete"
|
||||
bind:onColorTap="onColorTap" />
|
||||
</view>
|
||||
<view class="shape-list-empty" wx:if="{{!shapeList.length}}">
|
||||
<view class="empty-icon">
|
||||
<text class="toy-icon toy-icon-guide"></text>
|
||||
</view>
|
||||
<view class="empty-title">还没有选择图形</view>
|
||||
<view class="empty-desc"
|
||||
>请点击上方“选择图形”或使用“随机生成”开始创建</view
|
||||
>
|
||||
</view>
|
||||
</view>
|
||||
<shape-picker
|
||||
selectedShapeList="{{shapeList}}"
|
||||
show="{{showSelectShapePopup}}"
|
||||
selectedShapeIndex="{{selectedShapeIndex}}"
|
||||
bind:onClose="closeSelectShapePopup"
|
||||
bind:onChange="onChangeShape" />
|
||||
<color-picker
|
||||
show="{{showColorPopup}}"
|
||||
currentColor="{{currentColor}}"
|
||||
bind:onClose="onCloseColorPopup"
|
||||
bind:onChange="onChangeColor" />
|
||||
|
||||
<view id="previewWrapper" class="wrapper">
|
||||
<text class="wrapper-title">预览打印效果</text>
|
||||
<view
|
||||
wx:if="{{!isPCDevtool}}"
|
||||
id="canvasWrapper"
|
||||
class="canvas-wrapper">
|
||||
<canvas
|
||||
type="2d"
|
||||
id="canvasContent"
|
||||
class="canvas-content"
|
||||
style="width:{{boxWidth}}px;height:{{boxHeight}}px" />
|
||||
</view>
|
||||
</view>
|
||||
<view class="empty"></view>
|
||||
</view>
|
||||
<share-guide-popup
|
||||
show="{{showShareDialog}}"
|
||||
bind:onClose="onCloseShareDialog"
|
||||
bind:onShareSuccess="onShareSuccess" />
|
||||
<view class="bottom-btn-box">
|
||||
<toy-button
|
||||
openType="share"
|
||||
type="green"
|
||||
flat="{{true}}"
|
||||
bind:click="onShareAppMessage"
|
||||
width="220rpx"
|
||||
height="80rpx"
|
||||
icon="wechat"
|
||||
icon-class-prefix="toy-icon">
|
||||
分享
|
||||
</toy-button>
|
||||
<toy-button
|
||||
type="primary"
|
||||
flat="{{true}}"
|
||||
bind:click="exportToPrint"
|
||||
width="420rpx"
|
||||
height="80rpx"
|
||||
disabled="{{shapeList.length <= 0}}"
|
||||
icon="download"
|
||||
icon-class-prefix="toy-icon">
|
||||
下载打印
|
||||
</toy-button>
|
||||
</view>
|
||||
@@ -4,7 +4,7 @@
|
||||
*/
|
||||
|
||||
import { createPage, PageCommonMethodsConfig } from '../../../base/pageMixin';
|
||||
|
||||
import { FOCUS_FUNCTION_TYPES } from '../../../constants/focusFunctions';
|
||||
/**
|
||||
* 专注力模块的函数类型定义
|
||||
*/
|
||||
@@ -14,24 +14,6 @@ export interface FocusFunctionType {
|
||||
desc: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* 专注力模块的函数列表
|
||||
* TODO: 根据实际需求补充完整的功能列表
|
||||
*/
|
||||
export const FOCUS_FUNCTION_TYPES: FocusFunctionType[] = [
|
||||
{
|
||||
id: 'grid-drawing',
|
||||
title: '格子仿画',
|
||||
desc: '在格子中绘制颜色,形成各种形状',
|
||||
},
|
||||
// 可以在这里添加更多专注力相关的功能
|
||||
// {
|
||||
// id: 'pattern-memory',
|
||||
// title: '图案记忆',
|
||||
// desc: '记住并重现图案',
|
||||
// },
|
||||
];
|
||||
|
||||
/**
|
||||
* 专注力模块的分享配置
|
||||
*/
|
||||
|
||||
@@ -84,29 +84,54 @@ class GridDraw extends BaseDrawService {
|
||||
canvasWidth: number;
|
||||
startY: number;
|
||||
}): Promise<void> {
|
||||
const { ctx, gridData, canvasWidth, startY } = params;
|
||||
const { ctx, gridData, canvasWidth } = params;
|
||||
let { startY } = params;
|
||||
const { config, groups, groupsPerRow, totalRows } = gridData;
|
||||
const { rows, cols } = config;
|
||||
|
||||
startY = startY + 30;
|
||||
|
||||
// 计算网格尺寸
|
||||
const margin = 40; // 左右边距
|
||||
const groupSpacing = 20; // 组之间的间距
|
||||
const rowSpacing = 30; // 行之间的间距
|
||||
const dividerWidth = 2; // 分割线宽度
|
||||
const gridSpacing = 20; // 填充网格和空网格之间的间距
|
||||
const groupSpacing = 40; // 两组之间的间距(一行中两组格子仿画中间)
|
||||
const rowSpacing = 50; // 行之间的间距
|
||||
const dividerWidth = 1; // 分割线宽度
|
||||
|
||||
// 计算每组网格的尺寸
|
||||
const availableWidth = canvasWidth - margin * 2;
|
||||
const totalGroupsPerRow = groupsPerRow * 2; // 每组包含填充和空两个网格
|
||||
const groupWidth =
|
||||
const totalGridsPerRow = groupsPerRow * 2; // 每组包含填充和空两个网格
|
||||
const gridWidth =
|
||||
(availableWidth -
|
||||
(groupsPerRow - 1) * dividerWidth -
|
||||
(totalGroupsPerRow - 1) * groupSpacing) /
|
||||
totalGroupsPerRow;
|
||||
const cellSize = Math.floor(groupWidth / cols);
|
||||
const gridWidth = cellSize * cols;
|
||||
(groupsPerRow - 1) * groupSpacing -
|
||||
(totalGridsPerRow - 1) * gridSpacing) /
|
||||
totalGridsPerRow;
|
||||
const cellSize = Math.floor(gridWidth / cols);
|
||||
const actualGridWidth = cellSize * cols;
|
||||
const gridHeight = cellSize * rows;
|
||||
|
||||
let currentY = startY + 30; // 顶部间距
|
||||
const firstRowStartY = startY + 30; // 顶部间距
|
||||
const lastRowEndY =
|
||||
firstRowStartY +
|
||||
totalRows * gridHeight +
|
||||
(totalRows - 1) * rowSpacing;
|
||||
|
||||
// 计算第一行的起始X位置(居中)
|
||||
const rowTotalWidth =
|
||||
totalGridsPerRow * actualGridWidth +
|
||||
(totalGridsPerRow - 1) * gridSpacing +
|
||||
(groupsPerRow - 1) * groupSpacing;
|
||||
const rowStartX = margin + (availableWidth - rowTotalWidth) / 2;
|
||||
|
||||
// 计算中间垂直分割线的X位置(两组之间的位置)
|
||||
const middleDividerX =
|
||||
groupsPerRow > 1
|
||||
? rowStartX +
|
||||
actualGridWidth +
|
||||
gridSpacing +
|
||||
actualGridWidth +
|
||||
groupSpacing / 2
|
||||
: null;
|
||||
|
||||
// 遍历每一行
|
||||
for (let rowIndex = 0; rowIndex < totalRows; rowIndex++) {
|
||||
@@ -116,13 +141,8 @@ class GridDraw extends BaseDrawService {
|
||||
rowStartIndex + groupsPerRow,
|
||||
);
|
||||
|
||||
// 计算当前行的起始X位置(居中)
|
||||
const rowTotalWidth =
|
||||
totalGroupsPerRow * gridWidth +
|
||||
(totalGroupsPerRow - 1) * groupSpacing +
|
||||
(groupsPerRow - 1) * dividerWidth;
|
||||
const rowStartX = margin + (availableWidth - rowTotalWidth) / 2;
|
||||
|
||||
const currentY =
|
||||
firstRowStartY + rowIndex * (gridHeight + rowSpacing);
|
||||
let currentX = rowStartX;
|
||||
|
||||
// 遍历当前行的每一组
|
||||
@@ -138,7 +158,7 @@ class GridDraw extends BaseDrawService {
|
||||
ctx,
|
||||
gridStartX: currentX,
|
||||
gridStartY: currentY,
|
||||
gridWidth,
|
||||
gridWidth: actualGridWidth,
|
||||
gridHeight,
|
||||
cellSize,
|
||||
rows,
|
||||
@@ -147,14 +167,14 @@ class GridDraw extends BaseDrawService {
|
||||
config,
|
||||
});
|
||||
|
||||
currentX += gridWidth + groupSpacing;
|
||||
currentX += actualGridWidth + gridSpacing;
|
||||
|
||||
// 绘制空的网格(右侧)
|
||||
this.drawSingleGrid({
|
||||
ctx,
|
||||
gridStartX: currentX,
|
||||
gridStartY: currentY,
|
||||
gridWidth,
|
||||
gridWidth: actualGridWidth,
|
||||
gridHeight,
|
||||
cellSize,
|
||||
rows,
|
||||
@@ -163,32 +183,39 @@ class GridDraw extends BaseDrawService {
|
||||
config,
|
||||
});
|
||||
|
||||
currentX += gridWidth;
|
||||
currentX += actualGridWidth;
|
||||
|
||||
// 如果不是最后一组,绘制垂直分割线
|
||||
// 如果不是最后一组,添加组间距
|
||||
if (groupIndex < rowGroups.length - 1) {
|
||||
ctx.strokeStyle = '#000000';
|
||||
ctx.lineWidth = dividerWidth;
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(currentX, currentY);
|
||||
ctx.lineTo(currentX, currentY + gridHeight);
|
||||
ctx.stroke();
|
||||
currentX += dividerWidth;
|
||||
currentX += groupSpacing;
|
||||
}
|
||||
}
|
||||
|
||||
currentY += gridHeight + rowSpacing;
|
||||
|
||||
// 如果不是最后一行,绘制水平分割线
|
||||
if (rowIndex < totalRows - 1) {
|
||||
ctx.strokeStyle = '#000000';
|
||||
const lineY = currentY + gridHeight + rowSpacing / 2;
|
||||
ctx.strokeStyle = '#999';
|
||||
ctx.lineWidth = dividerWidth;
|
||||
ctx.setLineDash([4, 4]); // 虚线
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(margin, currentY - rowSpacing / 2);
|
||||
ctx.lineTo(canvasWidth - margin, currentY - rowSpacing / 2);
|
||||
ctx.moveTo(margin, lineY);
|
||||
ctx.lineTo(canvasWidth - margin, lineY);
|
||||
ctx.stroke();
|
||||
ctx.setLineDash([]); // 重置为实线
|
||||
}
|
||||
}
|
||||
|
||||
// 绘制中间垂直分割线(贯穿所有行)
|
||||
if (middleDividerX !== null && groupsPerRow > 1) {
|
||||
ctx.strokeStyle = '#999';
|
||||
ctx.lineWidth = dividerWidth;
|
||||
ctx.setLineDash([4, 4]); // 虚线
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(middleDividerX, firstRowStartY);
|
||||
ctx.lineTo(middleDividerX, lastRowEndY);
|
||||
ctx.stroke();
|
||||
ctx.setLineDash([]); // 重置为实线
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -220,7 +247,7 @@ class GridDraw extends BaseDrawService {
|
||||
} = params;
|
||||
|
||||
// 绘制网格线
|
||||
ctx.strokeStyle = config.gridLineColor || '#000000';
|
||||
ctx.strokeStyle = config.gridLineColor || '#999';
|
||||
ctx.lineWidth = config.gridLineWidth || 1;
|
||||
ctx.setLineDash([]); // 实线
|
||||
|
||||
|
||||
@@ -3,109 +3,686 @@
|
||||
* 适用于入门级,低龄儿童
|
||||
*/
|
||||
|
||||
import { GridCell, ShapeTemplate } from '../types/gridTypes';
|
||||
import { ShapeTemplate } from '../types/gridTypes';
|
||||
|
||||
// ==================== 3x3 形状模板 ====================
|
||||
|
||||
/** 简单十字形 */
|
||||
export const CROSS_3X3: ShapeTemplate = {
|
||||
id: 'cross-3x3-001',
|
||||
name: '十字形',
|
||||
recommendedSize: { rows: 3, cols: 3 },
|
||||
category: 'geometric',
|
||||
difficulty: 1,
|
||||
supportSymmetry: true,
|
||||
symmetryType: 'both',
|
||||
isComplete: true,
|
||||
cells: [
|
||||
{ x: 1, y: 0, color: '#FFFF00' }, // 顶部
|
||||
{ x: 0, y: 1, color: '#FFFF00' }, // 左侧
|
||||
{ x: 1, y: 1, color: '#FFFF00' }, // 中心
|
||||
{ x: 2, y: 1, color: '#FFFF00' }, // 右侧
|
||||
{ x: 1, y: 2, color: '#FFFF00' }, // 底部
|
||||
],
|
||||
};
|
||||
|
||||
/** L形 */
|
||||
export const L_SHAPE_3X3: ShapeTemplate = {
|
||||
id: 'l-3x3-001',
|
||||
name: 'L形',
|
||||
recommendedSize: { rows: 3, cols: 3 },
|
||||
category: 'geometric',
|
||||
difficulty: 1,
|
||||
supportSymmetry: false,
|
||||
isComplete: true,
|
||||
cells: [
|
||||
{ x: 0, y: 0, color: '#0000FF' },
|
||||
{ x: 0, y: 1, color: '#0000FF' },
|
||||
{ x: 0, y: 2, color: '#0000FF' },
|
||||
{ x: 1, y: 2, color: '#0000FF' },
|
||||
{ x: 2, y: 2, color: '#0000FF' },
|
||||
],
|
||||
};
|
||||
|
||||
/** 对角线 */
|
||||
export const DIAGONAL_3X3: ShapeTemplate = {
|
||||
id: 'diagonal-3x3-001',
|
||||
name: '对角线',
|
||||
recommendedSize: { rows: 3, cols: 3 },
|
||||
category: 'geometric',
|
||||
difficulty: 1,
|
||||
supportSymmetry: true,
|
||||
symmetryType: 'both',
|
||||
isComplete: true,
|
||||
cells: [
|
||||
{ x: 0, y: 0, color: '#FF0000' },
|
||||
{ x: 1, y: 1, color: '#FF0000' },
|
||||
{ x: 2, y: 2, color: '#FF0000' },
|
||||
],
|
||||
};
|
||||
|
||||
/** 小房子 */
|
||||
export const HOUSE_3X3: ShapeTemplate = {
|
||||
id: 'house-3x3-001',
|
||||
name: '小房子',
|
||||
recommendedSize: { rows: 3, cols: 3 },
|
||||
category: 'object',
|
||||
difficulty: 1,
|
||||
supportSymmetry: true,
|
||||
symmetryType: 'vertical',
|
||||
isComplete: true,
|
||||
cells: [
|
||||
{ x: 1, y: 0, color: '#FF0000' }, // 屋顶
|
||||
{ x: 0, y: 1, color: '#FFFF00' }, // 左侧墙
|
||||
{ x: 1, y: 1, color: '#FFFF00' }, // 中间墙
|
||||
{ x: 2, y: 1, color: '#FFFF00' }, // 右侧墙
|
||||
{ x: 1, y: 2, color: '#8B4513' }, // 门
|
||||
],
|
||||
};
|
||||
|
||||
/** 小星星 */
|
||||
export const STAR_3X3: ShapeTemplate = {
|
||||
id: 'star-3x3-001',
|
||||
name: '小星星',
|
||||
recommendedSize: { rows: 3, cols: 3 },
|
||||
category: 'geometric',
|
||||
difficulty: 1,
|
||||
supportSymmetry: true,
|
||||
symmetryType: 'both',
|
||||
isComplete: true,
|
||||
cells: [
|
||||
{ x: 1, y: 0, color: '#FFD700' }, // 顶部
|
||||
{ x: 0, y: 1, color: '#FFD700' },
|
||||
{ x: 1, y: 1, color: '#FFD700' }, // 中心
|
||||
{ x: 2, y: 1, color: '#FFD700' },
|
||||
{ x: 1, y: 2, color: '#FFD700' }, // 底部
|
||||
],
|
||||
};
|
||||
|
||||
/** 所有 3x3 形状模板 */
|
||||
/** 所有 3x3 形状模板 总共39个形状模板 */
|
||||
export const ALL_3X3_SHAPES: ShapeTemplate[] = [
|
||||
CROSS_3X3,
|
||||
L_SHAPE_3X3,
|
||||
DIAGONAL_3X3,
|
||||
HOUSE_3X3,
|
||||
STAR_3X3,
|
||||
/** 简单十字形 */
|
||||
{
|
||||
id: 'cross-3x3-001',
|
||||
name: '十字形',
|
||||
category: 'geometric',
|
||||
difficulty: 1,
|
||||
supportSymmetry: true,
|
||||
symmetryType: 'both',
|
||||
isComplete: true,
|
||||
cells: [
|
||||
{ x: 1, y: 0, color: '#FFE176' }, // 顶部 - 黄色
|
||||
{ x: 0, y: 1, color: '#F9A857' }, // 左侧 - 橙色
|
||||
{ x: 1, y: 1, color: '#ED6D50' }, // 中心 - 红色
|
||||
{ x: 2, y: 1, color: '#F9A857' }, // 右侧 - 橙色
|
||||
{ x: 1, y: 2, color: '#FFE176' }, // 底部 - 黄色
|
||||
],
|
||||
},
|
||||
/** L形 */
|
||||
{
|
||||
id: 'l-3x3-001',
|
||||
name: 'L形',
|
||||
category: 'geometric',
|
||||
difficulty: 1,
|
||||
supportSymmetry: false,
|
||||
isComplete: true,
|
||||
cells: [
|
||||
{ x: 0, y: 0, color: '#79A7ED' }, // 蓝色
|
||||
{ x: 0, y: 1, color: '#6CD2EA' }, // 浅蓝
|
||||
{ x: 0, y: 2, color: '#53D1B6' }, // 青色
|
||||
{ x: 1, y: 2, color: '#B2D94B' }, // 绿色
|
||||
{ x: 2, y: 2, color: '#FFE176' }, // 黄色
|
||||
],
|
||||
},
|
||||
/** 对角线 */
|
||||
{
|
||||
id: 'diagonal-3x3-001',
|
||||
name: '对角线',
|
||||
category: 'geometric',
|
||||
difficulty: 1,
|
||||
supportSymmetry: true,
|
||||
symmetryType: 'both',
|
||||
isComplete: true,
|
||||
cells: [
|
||||
{ x: 0, y: 0, color: '#ED6D50' }, // 红色
|
||||
{ x: 1, y: 1, color: '#F9A857' }, // 橙色
|
||||
{ x: 2, y: 2, color: '#FFE176' }, // 黄色
|
||||
],
|
||||
},
|
||||
|
||||
/** 反向对角线 */
|
||||
{
|
||||
id: 'reverse-diagonal-3x3-001',
|
||||
name: '反向对角线',
|
||||
category: 'geometric',
|
||||
difficulty: 1,
|
||||
supportSymmetry: true,
|
||||
symmetryType: 'both',
|
||||
isComplete: true,
|
||||
cells: [
|
||||
{ x: 0, y: 2, color: '#F2A4C0' },
|
||||
{ x: 1, y: 1, color: '#79A7ED' },
|
||||
{ x: 2, y: 0, color: '#B2D94B' },
|
||||
],
|
||||
},
|
||||
|
||||
/** 小房子 */
|
||||
{
|
||||
id: 'house-3x3-001',
|
||||
name: '小房子',
|
||||
category: 'object',
|
||||
difficulty: 1,
|
||||
supportSymmetry: true,
|
||||
symmetryType: 'vertical',
|
||||
isComplete: true,
|
||||
cells: [
|
||||
{ x: 1, y: 0, color: '#ED6D50' }, // 屋顶
|
||||
{ x: 0, y: 1, color: '#FFE176' }, // 左侧墙
|
||||
{ x: 1, y: 1, color: '#FFE176' }, // 中间墙
|
||||
{ x: 2, y: 1, color: '#FFE176' }, // 右侧墙
|
||||
{ x: 1, y: 2, color: '#BC8F71' }, // 门
|
||||
],
|
||||
},
|
||||
|
||||
/** 小星星 */
|
||||
{
|
||||
id: 'star-3x3-001',
|
||||
name: '小星星',
|
||||
category: 'geometric',
|
||||
difficulty: 1,
|
||||
supportSymmetry: true,
|
||||
symmetryType: 'both',
|
||||
isComplete: true,
|
||||
cells: [
|
||||
{ x: 1, y: 0, color: '#FFE176' }, // 顶部 - 黄色
|
||||
{ x: 0, y: 1, color: '#F9A857' }, // 左侧 - 橙色
|
||||
{ x: 1, y: 1, color: '#ED6D50' }, // 中心 - 红色
|
||||
{ x: 2, y: 1, color: '#F9A857' }, // 右侧 - 橙色
|
||||
{ x: 1, y: 2, color: '#FFE176' }, // 底部 - 黄色
|
||||
],
|
||||
},
|
||||
|
||||
/** T形 */
|
||||
{
|
||||
id: 't-3x3-001',
|
||||
name: 'T形',
|
||||
category: 'geometric',
|
||||
difficulty: 1,
|
||||
supportSymmetry: true,
|
||||
symmetryType: 'vertical',
|
||||
isComplete: true,
|
||||
cells: [
|
||||
{ x: 0, y: 0, color: '#53D1B6' }, // 青色
|
||||
{ x: 1, y: 0, color: '#6CD2EA' }, // 浅蓝
|
||||
{ x: 2, y: 0, color: '#53D1B6' }, // 青色
|
||||
{ x: 1, y: 1, color: '#79A7ED' }, // 蓝色
|
||||
{ x: 1, y: 2, color: '#6CD2EA' }, // 浅蓝
|
||||
],
|
||||
},
|
||||
|
||||
/** 倒T形 */
|
||||
{
|
||||
id: 'reverse-t-3x3-001',
|
||||
name: '倒T形',
|
||||
category: 'geometric',
|
||||
difficulty: 1,
|
||||
supportSymmetry: true,
|
||||
symmetryType: 'vertical',
|
||||
isComplete: true,
|
||||
cells: [
|
||||
{ x: 0, y: 2, color: '#ED6D50' },
|
||||
{ x: 1, y: 2, color: '#F9A857' },
|
||||
{ x: 2, y: 2, color: '#FFE176' },
|
||||
{ x: 1, y: 1, color: '#B2D94B' },
|
||||
{ x: 1, y: 0, color: '#79A7ED' },
|
||||
],
|
||||
},
|
||||
|
||||
/** 三角形 */
|
||||
{
|
||||
id: 'triangle-3x3-001',
|
||||
name: '三角形',
|
||||
category: 'geometric',
|
||||
difficulty: 1,
|
||||
supportSymmetry: true,
|
||||
symmetryType: 'vertical',
|
||||
isComplete: true,
|
||||
cells: [
|
||||
{ x: 1, y: 0, color: '#FFE176' }, // 顶部 - 黄色
|
||||
{ x: 0, y: 1, color: '#F9A857' }, // 左侧 - 橙色
|
||||
{ x: 1, y: 1, color: '#ED6D50' }, // 中心 - 红色
|
||||
{ x: 2, y: 1, color: '#F9A857' }, // 右侧 - 橙色
|
||||
{ x: 0, y: 2, color: '#F2A4C0' }, // 左下 - 粉色
|
||||
{ x: 1, y: 2, color: '#ED6D50' }, // 中下 - 红色
|
||||
{ x: 2, y: 2, color: '#F2A4C0' }, // 右下 - 粉色
|
||||
],
|
||||
},
|
||||
|
||||
/** 正方形 */
|
||||
{
|
||||
id: 'square-3x3-001',
|
||||
name: '正方形',
|
||||
category: 'geometric',
|
||||
difficulty: 1,
|
||||
supportSymmetry: true,
|
||||
symmetryType: 'both',
|
||||
isComplete: true,
|
||||
cells: [
|
||||
{ x: 0, y: 0, color: '#9C98DE' }, // 紫色
|
||||
{ x: 1, y: 0, color: '#F2A4C0' }, // 粉色
|
||||
{ x: 0, y: 1, color: '#F2A4C0' }, // 粉色
|
||||
{ x: 1, y: 1, color: '#9C98DE' }, // 紫色
|
||||
],
|
||||
},
|
||||
|
||||
/** 向上箭头 */
|
||||
{
|
||||
id: 'arrow-up-3x3-001',
|
||||
name: '向上箭头',
|
||||
category: 'geometric',
|
||||
difficulty: 1,
|
||||
supportSymmetry: true,
|
||||
symmetryType: 'vertical',
|
||||
isComplete: true,
|
||||
cells: [
|
||||
{ x: 1, y: 0, color: '#6CD2EA' }, // 箭头顶部 - 浅蓝
|
||||
{ x: 0, y: 1, color: '#53D1B6' }, // 左侧 - 青色
|
||||
{ x: 1, y: 1, color: '#79A7ED' }, // 中心 - 蓝色
|
||||
{ x: 2, y: 1, color: '#53D1B6' }, // 右侧 - 青色
|
||||
{ x: 1, y: 2, color: '#6CD2EA' }, // 箭头杆 - 浅蓝
|
||||
],
|
||||
},
|
||||
|
||||
/** 数字7 */
|
||||
{
|
||||
id: 'number-7-3x3-001',
|
||||
name: '数字7',
|
||||
category: 'geometric',
|
||||
difficulty: 1,
|
||||
supportSymmetry: false,
|
||||
isComplete: true,
|
||||
cells: [
|
||||
{ x: 0, y: 0, color: '#FC9B6C' }, // 橙色
|
||||
{ x: 1, y: 0, color: '#F9A857' }, // 浅橙
|
||||
{ x: 2, y: 0, color: '#ED6D50' }, // 红色
|
||||
{ x: 2, y: 1, color: '#F9A857' }, // 浅橙
|
||||
{ x: 1, y: 2, color: '#ED6D50' }, // 红色
|
||||
{ x: 2, y: 2, color: '#FC9B6C' }, // 橙色
|
||||
],
|
||||
},
|
||||
|
||||
/** 边框 */
|
||||
{
|
||||
id: 'frame-3x3-001',
|
||||
name: '边框',
|
||||
category: 'geometric',
|
||||
difficulty: 1,
|
||||
supportSymmetry: true,
|
||||
symmetryType: 'both',
|
||||
isComplete: true,
|
||||
cells: [
|
||||
{ x: 0, y: 0, color: '#B2D94B' }, // 绿色
|
||||
{ x: 1, y: 0, color: '#53D1B6' }, // 青色
|
||||
{ x: 2, y: 0, color: '#B2D94B' }, // 绿色
|
||||
{ x: 0, y: 1, color: '#6CD2EA' }, // 浅蓝
|
||||
{ x: 2, y: 1, color: '#6CD2EA' }, // 浅蓝
|
||||
{ x: 0, y: 2, color: '#B2D94B' }, // 绿色
|
||||
{ x: 1, y: 2, color: '#53D1B6' }, // 青色
|
||||
{ x: 2, y: 2, color: '#B2D94B' }, // 绿色
|
||||
],
|
||||
},
|
||||
|
||||
/** 加号(大) */
|
||||
{
|
||||
id: 'plus-3x3-001',
|
||||
name: '加号',
|
||||
category: 'geometric',
|
||||
difficulty: 1,
|
||||
supportSymmetry: true,
|
||||
symmetryType: 'both',
|
||||
isComplete: true,
|
||||
cells: [
|
||||
{ x: 1, y: 0, color: '#F2A4C0' }, // 粉色
|
||||
{ x: 0, y: 1, color: '#ED6D50' }, // 红色
|
||||
{ x: 1, y: 1, color: '#F9A857' }, // 橙色
|
||||
{ x: 2, y: 1, color: '#ED6D50' }, // 红色
|
||||
{ x: 1, y: 2, color: '#F2A4C0' }, // 粉色
|
||||
],
|
||||
},
|
||||
|
||||
/** 点阵 */
|
||||
{
|
||||
id: 'dots-3x3-001',
|
||||
name: '点阵',
|
||||
category: 'geometric',
|
||||
difficulty: 1,
|
||||
supportSymmetry: true,
|
||||
symmetryType: 'both',
|
||||
isComplete: true,
|
||||
cells: [
|
||||
{ x: 0, y: 0, color: '#79A7ED' }, // 蓝色
|
||||
{ x: 2, y: 0, color: '#6CD2EA' }, // 浅蓝
|
||||
{ x: 1, y: 1, color: '#53D1B6' }, // 青色
|
||||
{ x: 0, y: 2, color: '#6CD2EA' }, // 浅蓝
|
||||
{ x: 2, y: 2, color: '#79A7ED' }, // 蓝色
|
||||
],
|
||||
},
|
||||
|
||||
/** 向下箭头 */
|
||||
{
|
||||
id: 'arrow-down-3x3-001',
|
||||
name: '向下箭头',
|
||||
category: 'geometric',
|
||||
difficulty: 1,
|
||||
supportSymmetry: true,
|
||||
symmetryType: 'vertical',
|
||||
isComplete: true,
|
||||
cells: [
|
||||
{ x: 1, y: 0, color: '#6CD2EA' }, // 箭头杆 - 浅蓝
|
||||
{ x: 0, y: 1, color: '#53D1B6' }, // 左侧 - 青色
|
||||
{ x: 1, y: 1, color: '#79A7ED' }, // 中心 - 蓝色
|
||||
{ x: 2, y: 1, color: '#53D1B6' }, // 右侧 - 青色
|
||||
{ x: 1, y: 2, color: '#6CD2EA' }, // 箭头底部 - 浅蓝
|
||||
],
|
||||
},
|
||||
|
||||
/** 菱形 */
|
||||
{
|
||||
id: 'diamond-3x3-001',
|
||||
name: '菱形',
|
||||
category: 'geometric',
|
||||
difficulty: 1,
|
||||
supportSymmetry: true,
|
||||
symmetryType: 'both',
|
||||
isComplete: true,
|
||||
cells: [
|
||||
{ x: 1, y: 0, color: '#FFE176' }, // 顶部 - 黄色
|
||||
{ x: 0, y: 1, color: '#F9A857' }, // 左侧 - 橙色
|
||||
{ x: 1, y: 1, color: '#ED6D50' }, // 中心 - 红色
|
||||
{ x: 2, y: 1, color: '#F9A857' }, // 右侧 - 橙色
|
||||
{ x: 1, y: 2, color: '#FFE176' }, // 底部 - 黄色
|
||||
],
|
||||
},
|
||||
|
||||
/** U形 */
|
||||
{
|
||||
id: 'u-3x3-001',
|
||||
name: 'U形',
|
||||
category: 'geometric',
|
||||
difficulty: 1,
|
||||
supportSymmetry: true,
|
||||
symmetryType: 'vertical',
|
||||
isComplete: true,
|
||||
cells: [
|
||||
{ x: 0, y: 0, color: '#53D1B6' }, // 青色
|
||||
{ x: 2, y: 0, color: '#53D1B6' }, // 青色
|
||||
{ x: 0, y: 1, color: '#6CD2EA' }, // 浅蓝
|
||||
{ x: 2, y: 1, color: '#6CD2EA' }, // 浅蓝
|
||||
{ x: 0, y: 2, color: '#79A7ED' }, // 蓝色
|
||||
{ x: 1, y: 2, color: '#B2D94B' }, // 绿色
|
||||
{ x: 2, y: 2, color: '#79A7ED' }, // 蓝色
|
||||
],
|
||||
},
|
||||
|
||||
/** C形 */
|
||||
{
|
||||
id: 'c-3x3-001',
|
||||
name: 'C形',
|
||||
category: 'geometric',
|
||||
difficulty: 1,
|
||||
supportSymmetry: false,
|
||||
isComplete: true,
|
||||
cells: [
|
||||
{ x: 0, y: 0, color: '#ED6D50' }, // 红色
|
||||
{ x: 1, y: 0, color: '#F9A857' }, // 橙色
|
||||
{ x: 0, y: 1, color: '#FFE176' }, // 黄色
|
||||
{ x: 0, y: 2, color: '#F9A857' }, // 橙色
|
||||
{ x: 1, y: 2, color: '#ED6D50' }, // 红色
|
||||
],
|
||||
},
|
||||
|
||||
/** 倒三角形 */
|
||||
{
|
||||
id: 'inverted-triangle-3x3-001',
|
||||
name: '倒三角形',
|
||||
category: 'geometric',
|
||||
difficulty: 1,
|
||||
supportSymmetry: true,
|
||||
symmetryType: 'vertical',
|
||||
isComplete: true,
|
||||
cells: [
|
||||
{ x: 0, y: 0, color: '#B2D94B' }, // 绿色
|
||||
{ x: 1, y: 0, color: '#53D1B6' }, // 青色
|
||||
{ x: 2, y: 0, color: '#B2D94B' }, // 绿色
|
||||
{ x: 0, y: 1, color: '#6CD2EA' }, // 浅蓝
|
||||
{ x: 1, y: 1, color: '#79A7ED' }, // 蓝色
|
||||
{ x: 2, y: 1, color: '#6CD2EA' }, // 浅蓝
|
||||
{ x: 1, y: 2, color: '#53D1B6' }, // 底部 - 青色
|
||||
],
|
||||
},
|
||||
|
||||
/** 数字1 */
|
||||
{
|
||||
id: 'number-1-3x3-001',
|
||||
name: '数字1',
|
||||
category: 'geometric',
|
||||
difficulty: 1,
|
||||
supportSymmetry: true,
|
||||
symmetryType: 'vertical',
|
||||
isComplete: true,
|
||||
cells: [
|
||||
{ x: 1, y: 0, color: '#FC9B6C' }, // 橙色
|
||||
{ x: 1, y: 1, color: '#F9A857' }, // 浅橙
|
||||
{ x: 1, y: 2, color: '#ED6D50' }, // 红色
|
||||
],
|
||||
},
|
||||
|
||||
/** 数字4 */
|
||||
{
|
||||
id: 'number-4-3x3-001',
|
||||
name: '数字4',
|
||||
category: 'geometric',
|
||||
difficulty: 1,
|
||||
supportSymmetry: false,
|
||||
isComplete: true,
|
||||
cells: [
|
||||
{ x: 0, y: 0, color: '#F2A4C0' }, // 粉色
|
||||
{ x: 1, y: 0, color: '#ED6D50' }, // 红色
|
||||
{ x: 0, y: 1, color: '#F9A857' }, // 橙色
|
||||
{ x: 1, y: 1, color: '#FFE176' }, // 黄色
|
||||
{ x: 2, y: 1, color: '#F2A4C0' }, // 粉色
|
||||
{ x: 2, y: 2, color: '#ED6D50' }, // 红色
|
||||
],
|
||||
},
|
||||
|
||||
/** 圆形(3x3近似) */
|
||||
{
|
||||
id: 'circle-3x3-001',
|
||||
name: '圆形',
|
||||
category: 'geometric',
|
||||
difficulty: 1,
|
||||
supportSymmetry: true,
|
||||
symmetryType: 'both',
|
||||
isComplete: true,
|
||||
cells: [
|
||||
{ x: 1, y: 0, color: '#9C98DE' }, // 紫色
|
||||
{ x: 0, y: 1, color: '#F2A4C0' }, // 粉色
|
||||
{ x: 2, y: 1, color: '#F2A4C0' }, // 粉色
|
||||
{ x: 1, y: 2, color: '#9C98DE' }, // 紫色
|
||||
],
|
||||
},
|
||||
|
||||
/** 数字0 */
|
||||
{
|
||||
id: 'number-0-3x3-001',
|
||||
name: '数字0',
|
||||
category: 'geometric',
|
||||
difficulty: 1,
|
||||
supportSymmetry: true,
|
||||
symmetryType: 'both',
|
||||
isComplete: true,
|
||||
cells: [
|
||||
{ x: 0, y: 0, color: '#FFE176' }, // 黄色
|
||||
{ x: 1, y: 0, color: '#F9A857' }, // 橙色
|
||||
{ x: 2, y: 0, color: '#FFE176' }, // 黄色
|
||||
{ x: 0, y: 1, color: '#F9A857' }, // 橙色
|
||||
{ x: 2, y: 1, color: '#F9A857' }, // 橙色
|
||||
{ x: 0, y: 2, color: '#FFE176' }, // 黄色
|
||||
{ x: 1, y: 2, color: '#F9A857' }, // 橙色
|
||||
{ x: 2, y: 2, color: '#FFE176' }, // 黄色
|
||||
],
|
||||
},
|
||||
|
||||
/** 数字8 */
|
||||
{
|
||||
id: 'number-8-3x3-001',
|
||||
name: '数字8',
|
||||
category: 'geometric',
|
||||
difficulty: 1,
|
||||
supportSymmetry: true,
|
||||
symmetryType: 'both',
|
||||
isComplete: true,
|
||||
cells: [
|
||||
{ x: 0, y: 0, color: '#79A7ED' }, // 蓝色
|
||||
{ x: 1, y: 0, color: '#6CD2EA' }, // 浅蓝
|
||||
{ x: 2, y: 0, color: '#79A7ED' }, // 蓝色
|
||||
{ x: 0, y: 1, color: '#53D1B6' }, // 青色
|
||||
{ x: 1, y: 1, color: '#B2D94B' }, // 绿色
|
||||
{ x: 2, y: 1, color: '#53D1B6' }, // 青色
|
||||
{ x: 0, y: 2, color: '#79A7ED' }, // 蓝色
|
||||
{ x: 1, y: 2, color: '#6CD2EA' }, // 浅蓝
|
||||
{ x: 2, y: 2, color: '#79A7ED' }, // 蓝色
|
||||
],
|
||||
},
|
||||
|
||||
/** 多色十字形 */
|
||||
{
|
||||
id: 'colorful-cross-3x3-001',
|
||||
name: '多色十字形',
|
||||
category: 'geometric',
|
||||
difficulty: 1,
|
||||
supportSymmetry: true,
|
||||
symmetryType: 'both',
|
||||
isComplete: true,
|
||||
cells: [
|
||||
{ x: 1, y: 0, color: '#FFE176' }, // 顶部 - 黄色
|
||||
{ x: 0, y: 1, color: '#F9A857' }, // 左侧 - 橙色
|
||||
{ x: 1, y: 1, color: '#ED6D50' }, // 中心 - 红色
|
||||
{ x: 2, y: 1, color: '#F9A857' }, // 右侧 - 橙色
|
||||
{ x: 1, y: 2, color: '#FFE176' }, // 底部 - 黄色
|
||||
],
|
||||
},
|
||||
|
||||
/** 多色L形 */
|
||||
{
|
||||
id: 'colorful-l-3x3-001',
|
||||
name: '多色L形',
|
||||
category: 'geometric',
|
||||
difficulty: 1,
|
||||
supportSymmetry: false,
|
||||
isComplete: true,
|
||||
cells: [
|
||||
{ x: 0, y: 0, color: '#79A7ED' }, // 蓝色
|
||||
{ x: 0, y: 1, color: '#6CD2EA' }, // 浅蓝
|
||||
{ x: 0, y: 2, color: '#53D1B6' }, // 青色
|
||||
{ x: 1, y: 2, color: '#B2D94B' }, // 绿色
|
||||
{ x: 2, y: 2, color: '#FFE176' }, // 黄色
|
||||
],
|
||||
},
|
||||
|
||||
/** 多色星星 */
|
||||
{
|
||||
id: 'colorful-star-3x3-001',
|
||||
name: '多色星星',
|
||||
category: 'geometric',
|
||||
difficulty: 1,
|
||||
supportSymmetry: true,
|
||||
symmetryType: 'both',
|
||||
isComplete: true,
|
||||
cells: [
|
||||
{ x: 1, y: 0, color: '#FFE176' }, // 顶部 - 黄色
|
||||
{ x: 0, y: 1, color: '#F9A857' }, // 左侧 - 橙色
|
||||
{ x: 1, y: 1, color: '#ED6D50' }, // 中心 - 红色
|
||||
{ x: 2, y: 1, color: '#F9A857' }, // 右侧 - 橙色
|
||||
{ x: 1, y: 2, color: '#FFE176' }, // 底部 - 黄色
|
||||
],
|
||||
},
|
||||
|
||||
/** 多色小房子 */
|
||||
{
|
||||
id: 'colorful-house-3x3-001',
|
||||
name: '多色小房子',
|
||||
category: 'object',
|
||||
difficulty: 1,
|
||||
supportSymmetry: true,
|
||||
symmetryType: 'vertical',
|
||||
isComplete: true,
|
||||
cells: [
|
||||
{ x: 1, y: 0, color: '#ED6D50' }, // 屋顶 - 红色
|
||||
{ x: 0, y: 1, color: '#FFE176' }, // 左侧墙 - 黄色
|
||||
{ x: 1, y: 1, color: '#F9A857' }, // 中间墙 - 橙色
|
||||
{ x: 2, y: 1, color: '#FFE176' }, // 右侧墙 - 黄色
|
||||
{ x: 1, y: 2, color: '#BC8F71' }, // 门 - 棕色
|
||||
],
|
||||
},
|
||||
|
||||
/** 数字2 */
|
||||
{
|
||||
id: 'number-2-3x3-001',
|
||||
name: '数字2',
|
||||
category: 'geometric',
|
||||
difficulty: 2,
|
||||
supportSymmetry: false,
|
||||
isComplete: true,
|
||||
cells: [
|
||||
{ x: 0, y: 0, color: '#79A7ED' }, // 蓝色
|
||||
{ x: 1, y: 0, color: '#6CD2EA' }, // 浅蓝
|
||||
{ x: 2, y: 0, color: '#53D1B6' }, // 青色
|
||||
{ x: 2, y: 1, color: '#6CD2EA' }, // 浅蓝
|
||||
{ x: 0, y: 2, color: '#53D1B6' }, // 青色
|
||||
{ x: 1, y: 2, color: '#6CD2EA' }, // 浅蓝
|
||||
{ x: 2, y: 2, color: '#79A7ED' }, // 蓝色
|
||||
],
|
||||
},
|
||||
/** 数字3 */
|
||||
{
|
||||
id: 'number-3-3x3-001',
|
||||
name: '数字3',
|
||||
category: 'geometric',
|
||||
difficulty: 2,
|
||||
supportSymmetry: false,
|
||||
isComplete: true,
|
||||
cells: [
|
||||
{ x: 0, y: 0, color: '#6CD2EA' }, // 浅蓝
|
||||
{ x: 1, y: 0, color: '#53D1B6' }, // 青色
|
||||
{ x: 2, y: 0, color: '#79A7ED' }, // 蓝色
|
||||
{ x: 2, y: 1, color: '#53D1B6' }, // 青色
|
||||
{ x: 0, y: 2, color: '#79A7ED' }, // 蓝色
|
||||
{ x: 1, y: 2, color: '#53D1B6' }, // 青色
|
||||
{ x: 2, y: 2, color: '#6CD2EA' }, // 浅蓝
|
||||
],
|
||||
},
|
||||
|
||||
/** 数字5 */
|
||||
{
|
||||
id: 'number-5-3x3-001',
|
||||
name: '数字5',
|
||||
category: 'geometric',
|
||||
difficulty: 2,
|
||||
supportSymmetry: false,
|
||||
isComplete: true,
|
||||
cells: [
|
||||
{ x: 0, y: 0, color: '#53D1B6' }, // 青色
|
||||
{ x: 1, y: 0, color: '#6CD2EA' }, // 浅蓝
|
||||
{ x: 2, y: 0, color: '#79A7ED' }, // 蓝色
|
||||
{ x: 0, y: 1, color: '#6CD2EA' }, // 浅蓝
|
||||
{ x: 0, y: 2, color: '#79A7ED' }, // 蓝色
|
||||
{ x: 1, y: 2, color: '#6CD2EA' }, // 浅蓝
|
||||
{ x: 2, y: 2, color: '#53D1B6' }, // 青色
|
||||
],
|
||||
},
|
||||
|
||||
/** 数字6 */
|
||||
{
|
||||
id: 'number-6-3x3-001',
|
||||
name: '数字6',
|
||||
category: 'geometric',
|
||||
difficulty: 2,
|
||||
supportSymmetry: false,
|
||||
isComplete: true,
|
||||
cells: [
|
||||
{ x: 0, y: 0, color: '#B2D94B' }, // 绿色
|
||||
{ x: 1, y: 0, color: '#53D1B6' }, // 青色
|
||||
{ x: 0, y: 1, color: '#6CD2EA' }, // 浅蓝
|
||||
{ x: 0, y: 2, color: '#79A7ED' }, // 蓝色
|
||||
{ x: 1, y: 2, color: '#6CD2EA' }, // 浅蓝
|
||||
{ x: 2, y: 2, color: '#53D1B6' }, // 青色
|
||||
],
|
||||
},
|
||||
|
||||
/** 数字9 */
|
||||
{
|
||||
id: 'number-9-3x3-001',
|
||||
name: '数字9',
|
||||
category: 'geometric',
|
||||
difficulty: 2,
|
||||
supportSymmetry: false,
|
||||
isComplete: true,
|
||||
cells: [
|
||||
{ x: 0, y: 0, color: '#F2A4C0' }, // 粉色
|
||||
{ x: 1, y: 0, color: '#ED6D50' }, // 红色
|
||||
{ x: 2, y: 0, color: '#F9A857' }, // 橙色
|
||||
{ x: 0, y: 1, color: '#ED6D50' }, // 红色
|
||||
{ x: 2, y: 1, color: '#FFE176' }, // 黄色
|
||||
{ x: 1, y: 2, color: '#F9A857' }, // 橙色
|
||||
{ x: 2, y: 2, color: '#ED6D50' }, // 红色
|
||||
],
|
||||
},
|
||||
/** 字母A */
|
||||
{
|
||||
id: 'letter-a-3x3-001',
|
||||
name: '字母A',
|
||||
category: 'geometric',
|
||||
difficulty: 2,
|
||||
supportSymmetry: true,
|
||||
symmetryType: 'vertical',
|
||||
isComplete: true,
|
||||
cells: [
|
||||
{ x: 1, y: 0, color: '#FFE176' }, // 黄色
|
||||
{ x: 0, y: 1, color: '#F9A857' }, // 橙色
|
||||
{ x: 1, y: 1, color: '#ED6D50' }, // 红色
|
||||
{ x: 2, y: 1, color: '#F9A857' }, // 橙色
|
||||
{ x: 0, y: 2, color: '#FFE176' }, // 黄色
|
||||
{ x: 2, y: 2, color: '#FFE176' }, // 黄色
|
||||
],
|
||||
},
|
||||
/** 字母H */
|
||||
{
|
||||
id: 'letter-h-3x3-001',
|
||||
name: '字母H',
|
||||
category: 'geometric',
|
||||
difficulty: 2,
|
||||
supportSymmetry: true,
|
||||
symmetryType: 'vertical',
|
||||
isComplete: true,
|
||||
cells: [
|
||||
{ x: 0, y: 0, color: '#F9A857' }, // 橙色
|
||||
{ x: 2, y: 0, color: '#F9A857' }, // 橙色
|
||||
{ x: 0, y: 1, color: '#ED6D50' }, // 红色
|
||||
{ x: 1, y: 1, color: '#FFE176' }, // 黄色
|
||||
{ x: 2, y: 1, color: '#ED6D50' }, // 红色
|
||||
{ x: 0, y: 2, color: '#F9A857' }, // 橙色
|
||||
{ x: 2, y: 2, color: '#F9A857' }, // 橙色
|
||||
],
|
||||
},
|
||||
/** 字母O */
|
||||
{
|
||||
id: 'letter-o-3x3-001',
|
||||
name: '字母O',
|
||||
category: 'geometric',
|
||||
difficulty: 2,
|
||||
supportSymmetry: true,
|
||||
symmetryType: 'both',
|
||||
isComplete: true,
|
||||
cells: [
|
||||
{ x: 0, y: 0, color: '#ED6D50' }, // 红色
|
||||
{ x: 1, y: 0, color: '#F9A857' }, // 橙色
|
||||
{ x: 2, y: 0, color: '#ED6D50' }, // 红色
|
||||
{ x: 0, y: 1, color: '#F9A857' }, // 橙色
|
||||
{ x: 2, y: 1, color: '#F9A857' }, // 橙色
|
||||
{ x: 0, y: 2, color: '#ED6D50' }, // 红色
|
||||
{ x: 1, y: 2, color: '#F9A857' }, // 橙色
|
||||
{ x: 2, y: 2, color: '#ED6D50' }, // 红色
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
/**
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -30,12 +30,8 @@ export interface ShapeTemplate {
|
||||
id: string;
|
||||
/** 形状名称 */
|
||||
name: string;
|
||||
/** 推荐网格尺寸 */
|
||||
recommendedSize: { rows: number; cols: number };
|
||||
/** 形状数据(如果是对称形状,这里存储的是左半部分或上半部分) */
|
||||
cells: GridCell[];
|
||||
/** 颜色方案ID */
|
||||
colorSchemeId?: string;
|
||||
/** 分类 */
|
||||
category: 'animal' | 'object' | 'geometric' | 'character' | 'nature';
|
||||
/** 难度等级 1-5 */
|
||||
@@ -47,13 +43,3 @@ export interface ShapeTemplate {
|
||||
/** 是否已经是对称完整的图案(false表示只存储了半边) */
|
||||
isComplete?: boolean;
|
||||
}
|
||||
|
||||
/** 颜色方案 */
|
||||
export const COLOR_SCHEMES: Record<string, string[]> = {
|
||||
basic: ['#FF0000', '#00FF00', '#0000FF', '#FFFF00', '#FF00FF'],
|
||||
warm: ['#FF0000', '#FF7F00', '#FFFF00', '#FF69B4', '#FF4500'],
|
||||
cool: ['#00FFFF', '#0000FF', '#8A2BE2', '#00FF00', '#87CEEB'],
|
||||
halloween: ['#FF7F00', '#FFFF00', '#000000', '#90EE90', '#FF0000'],
|
||||
nature: ['#00FF00', '#90EE90', '#006400', '#FFFF00', '#8B4513'],
|
||||
rainbow: ['#FF0000', '#FF7F00', '#FFFF00', '#00FF00', '#0000FF', '#8A2BE2'],
|
||||
};
|
||||
|
||||
@@ -83,9 +83,13 @@ export function generateSymmetricalPattern(
|
||||
/**
|
||||
* 从形状模板生成完整的格子数据
|
||||
* @param template 形状模板
|
||||
* @param config 网格配置(用于对称生成)
|
||||
* @returns 完整的格子数据
|
||||
*/
|
||||
export function generateCompletePattern(template: ShapeTemplate): GridCell[] {
|
||||
export function generateCompletePattern(
|
||||
template: ShapeTemplate,
|
||||
config: GridConfig,
|
||||
): GridCell[] {
|
||||
if (template.isComplete) {
|
||||
// 如果已经是完整图案,直接返回
|
||||
return [...template.cells];
|
||||
@@ -95,10 +99,7 @@ export function generateCompletePattern(template: ShapeTemplate): GridCell[] {
|
||||
// 使用对称生成完整图案
|
||||
return generateSymmetricalPattern(
|
||||
template.cells,
|
||||
{
|
||||
rows: template.recommendedSize.rows,
|
||||
cols: template.recommendedSize.cols,
|
||||
},
|
||||
config,
|
||||
template.symmetryType,
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user