import { SHAPES, ShapeCard } from '../../constants/shapes'; import { WATER_COLORS, PAPER_SIZE } from '../../constants/colors'; import ShapeDrawService from '../../service/shapeDrawService'; import { checkAndSaveImage } from '../../utils/saveImage'; Page({ canvas: null as Canvas | null, ctx: null as RenderingContext | null, boxHeight: 0, boxWidth: 0, shapeDrawService: null as ShapeDrawService | null, data: { shapeList: [] as ShapeCard[], showSelectShapePopup: false, currentShapeId: '', showColorPopup: false, currentIndex: 0, currentColor: '', isPCDevtool: 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); } }, openSelectShapePopup(e: any) { const { key } = e.detail; this.setData({ showSelectShapePopup: true, currentShapeId: key }); }, closeSelectShapePopup() { this.setData({ showSelectShapePopup: false, currentShapeId: '' }); }, onChangeShape(e: any) { const { shapes } = e.detail; const prevShapeList: ShapeCard[] = this.data.shapeList || []; // 1. 保留已选图形的 fillColor,不变 // 2. 新增的图形分配未被占用的颜色,且不重复 // 获取所有可用颜色 const colorList = WATER_COLORS.basic12.map(item => item.hex); // 记录已被使用的颜色(只考虑当前 shapeList 中的 fillColor) const usedColors = prevShapeList.map(item => item.fillColor).filter(Boolean); // 新的 shapeList const newShapeList: ShapeCard[] = []; // 记录已分配的颜色,避免重复 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, currentShapeId: '', shapeList: newShapeList }, () => { // 绘制canvas 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((item, i) => i !== index); this.setData({ shapeList: newShapeList }, () => { // 绘制canvas this.drawCanvas(); }); }, onColorTap(e: any) { const { index, fillColor } = e.detail; console.log('shape Page onColorTap', index, fillColor); this.setData({ showColorPopup: true, currentColor: fillColor, currentIndex: index }); }, onCloseColorPopup() { this.setData({ showColorPopup: false, currentColor: '', currentIndex: 0 }); }, onChangeColor(e: any) { const { color } = e.detail; const { currentIndex } = this.data; this.setData({ showColorPopup: false, [`shapeList[${currentIndex}].fillColor`]: color }, () => { // 绘制canvas this.drawCanvas(); }) }, // 测试ShapeDrawService // testShapeDrawService() { // if (!this.shapeDrawService) { // wx.showToast({ // title: 'Canvas未初始化', // icon: 'none' // }); // return; // } // // 使用当前选中的图形进行测试 // const testShapes = this.data.shapeList.slice(0, 3); // 只测试前3个图形 // if (testShapes.length === 0) { // wx.showToast({ // title: '请先选择图形', // icon: 'none' // }); // return; // } // this.shapeDrawService.draw(testShapes); // wx.showToast({ // title: '绘制完成', // icon: 'success' // }); // }, onShareAppMessage() { return { title: '涂鸦丫-涂色|识字|画画|打印', path: '/pages/index/index', }; }, onShareTimeline() { return { title: '涂鸦丫-涂色|识字|画画|打印', query: '/pages/index/index', }; }, /** 下载打印 */ exportToPrint() { if (this.canvas && this.data.shapeList.length > 0) { checkAndSaveImage(this.canvas); return; } }, });