Files
doodle-mini/miniprogram/demoPages/textPaint2/textPaint.ts
T
2025-03-18 15:17:30 +08:00

167 lines
5.1 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
Page({
canvas: null as WechatMiniprogram.Canvas | null,
ctx: null as CanvasRenderingContext2D | null,
data: {
characters: ['鱼', '鸟', '牛', '羊'] as const, // 固定汉字类型
colorMap: new Map([
// 颜色映射关系
['鱼', '#2196F3'], // 蓝色
['鸟', '#FFEB3B'], // 黄色
['牛', '#FF9800'], // 橙色
['羊', '#9C27B0'], // 紫色
]),
matrix: [] as string[], // 随机汉字矩阵
selectedColor: '', // 当前选中颜色
selectedChar: '', // 当前选中汉字
},
onLoad() {
this.generateMatrix();
},
// 生成6列随机矩阵
generateMatrix() {
const shuffled = [...this.data.characters]
.sort(() => Math.random() - 0.5)
.concat(
...Array(42)
.fill(null)
.map(() => this.data.characters[Math.floor(Math.random() * 4)]),
);
this.setData({ matrix: shuffled.slice(0, 42) }); // 6列x7行
},
// 初始化A4画布(300DPI
initCanvas() {
const dpi = 300;
const width = 2480,
height = 3508; // A4精确像素
wx.createSelectorQuery()
.select('#canvas')
.node()
.exec((res) => {
const canvas = res[0].node;
this.canvas = canvas;
const ctx = canvas.getContext('2d');
this.ctx = ctx;
// 设置物理尺寸
canvas.width = width;
canvas.height = height;
// 适配屏幕显示
const ratio = wx.getWindowInfo().pixelRatio;
canvas.style.width = `${width / ratio}px`;
ctx.scale(ratio, ratio);
this.drawGameBoard(ctx);
});
},
// 绘制完整游戏界面
drawGameBoard(ctx?: CanvasRenderingContext2D) {
ctx = ctx || (this.ctx as CanvasRenderingContext2D);
ctx.clearRect(0, 0, 2480, 3508);
// 绘制标题
ctx.font = 'bold 80px "Microsoft Yahei"';
ctx.fillStyle = '#333';
ctx.fillText('找一找 涂 色', 1240 - ctx.measureText('找一找 涂 色').width / 2, 150);
// 绘制颜色示例(顶部)
this.drawColorLegend(ctx, 250);
// 绘制汉字矩阵(主体)
this.drawCharacterMatrix(ctx, 600);
},
// 绘制颜色示例
drawColorLegend(ctx: CanvasRenderingContext2D, y: number) {
let x = 500;
this.data.characters.forEach((char) => {
ctx.beginPath();
ctx.arc(x, y, 50, 0, Math.PI * 2);
ctx.fillStyle = this.data.colorMap.get(char) as string;
ctx.fill();
ctx.strokeStyle = '#333';
ctx.lineWidth = 4;
ctx.stroke();
x += 300;
});
},
// 绘制汉字矩阵(6列x7行)
drawCharacterMatrix(ctx: CanvasRenderingContext2D, startY: number) {
const cols = 6;
const cellSize = 350; // 每个单元格大小
this.data.matrix.forEach((char, index) => {
const row = Math.floor(index / cols);
const col = index % cols;
// 计算坐标
const x = 300 + col * cellSize;
const y = startY + row * cellSize;
// 绘制圆形
ctx.beginPath();
ctx.arc(x, y, 120, 0, Math.PI * 2);
ctx.fillStyle = '#fff';
ctx.fill();
ctx.strokeStyle = '#333';
ctx.lineWidth = 4;
ctx.stroke();
// 绘制汉字
ctx.font = 'bold 100px "Microsoft Yahei"';
ctx.fillStyle = this.data.colorMap.get(char) || '';
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
ctx.fillText(char, x, y);
});
},
// 点击颜色选择
handleColorSelect(e: WechatMiniprogram.TouchEvent) {
const index = e.currentTarget.dataset.index;
const selectedChar = this.data.characters[index];
this.setData({
selectedColor: this.data.colorMap.get(selectedChar),
selectedChar,
});
},
// 点击汉字涂色
handleCharacterTap(e: WechatMiniprogram.TouchEvent) {
const index = e.currentTarget.dataset.index;
if (!this.data.selectedColor) return;
const matrix = this.data.matrix.map((char, i) =>
i === index ? this.data.selectedChar : char,
);
this.setData({ matrix }, () => {
this.drawGameBoard();
});
},
// 导出A4图片
exportToPrint() {
if (this.canvas) {
wx.canvasToTempFilePath({
canvas: this.canvas,
fileType: 'png',
quality: 1,
success: (res) => {
wx.saveImageToPhotosAlbum({
filePath: res.tempFilePath,
success: () => wx.showToast({ title: '保存成功' }),
});
},
});
return;
}
},
});