224 lines
7.1 KiB
TypeScript
224 lines
7.1 KiB
TypeScript
import WordDrawService from '../../service/wordDrawService';
|
|
import { checkAndSaveImage } from '../../utils/saveImage';
|
|
import { PAPER_SIZE } from '../../constants/colors';
|
|
|
|
Page({
|
|
canvas: null as Canvas | null,
|
|
ctx: null as RenderingContext | null,
|
|
wordDrawService: null as WordDrawService | null,
|
|
svgWords: {} as Record<string, string[]>,
|
|
|
|
data: {
|
|
// 选中的汉字列表
|
|
words: ['赢', '张', '政'] as string[],
|
|
showSelectWordPopup: false,
|
|
showColorPopup: false,
|
|
currentKey: 0,
|
|
currentColor: '',
|
|
|
|
// 田字格配置
|
|
// rows: 10,
|
|
// cols: 12,
|
|
// rowsArray: [] as number[],
|
|
// colsArray: [] as number[],
|
|
boxWidth: 0,
|
|
boxHeight: 0,
|
|
},
|
|
|
|
onLoad() {
|
|
// this.initGrid();
|
|
this.loadSvgWords();
|
|
},
|
|
|
|
onReady() {
|
|
this.setCanvasBoxSize();
|
|
},
|
|
|
|
loadSvgWords() {
|
|
const fs = wx.getFileSystemManager();
|
|
fs.readFile({
|
|
filePath: 'constants/svgWords.json', // JSON文件路径,相对于项目根目录
|
|
encoding: 'utf8', // 重要:指定编码为utf8以读取文本内容
|
|
success: (res) => {
|
|
try {
|
|
wx.showToast({ title: '加载中...', icon: 'loading' });
|
|
const parsedData = JSON.parse(res.data as string);
|
|
this.svgWords = parsedData;
|
|
console.log('this.svgWords.length----:', Object.keys(this.svgWords).length)
|
|
wx.hideToast();
|
|
console.log('SVG words loaded successfully');
|
|
const { words } = this.data as any;
|
|
if (words && words.length > 0) {
|
|
this.drawPracticeSheet().catch(console.error);
|
|
}
|
|
} catch (e) {
|
|
console.error('解析JSON失败', e);
|
|
}
|
|
},
|
|
fail: (err) => {
|
|
console.error('读取文件失败', err);
|
|
wx.hideToast();
|
|
}
|
|
});
|
|
},
|
|
|
|
// 输入组件回调
|
|
onConfirmInput(e: any) {
|
|
const value: string = (e && e.detail && e.detail.value) || '';
|
|
const text = (value || '').trim();
|
|
if (!text) return;
|
|
|
|
if (!this.isChineseText(text)) {
|
|
wx.showToast({ title: '请输入汉字', icon: 'none' });
|
|
return;
|
|
}
|
|
|
|
const chars = this.splitToSingleChars(text);
|
|
const { words } = this.data as any;
|
|
const exists = new Set(words);
|
|
const newWords = [...words];
|
|
chars.forEach((ch) => {
|
|
if (!exists.has(ch)) {
|
|
newWords.push(ch);
|
|
}
|
|
});
|
|
this.setData({ words: newWords }, () => this.drawPracticeSheet().catch(console.error));
|
|
},
|
|
|
|
// 选择面板
|
|
openSelectWordPopup() {
|
|
this.setData({ showSelectWordPopup: true });
|
|
},
|
|
closeSelectWordPopup() {
|
|
this.setData({ showSelectWordPopup: false });
|
|
},
|
|
onChangeWord(e: any) {
|
|
const selectedWords = e.detail.selectedWords as string[];
|
|
const newWords = [...this.data.words, ...selectedWords];
|
|
this.setData({ words: newWords, showSelectWordPopup: false }, () => this.drawPracticeSheet().catch(console.error));
|
|
},
|
|
|
|
// 删除与颜色
|
|
deleteWordCard(e: any) {
|
|
const { word } = e.detail;
|
|
const { words } = this.data as any;
|
|
const next = words.filter((w: string) => w !== word);
|
|
this.setData({ words: next }, () => this.drawPracticeSheet().catch(console.error));
|
|
},
|
|
|
|
// 校验 & 分割
|
|
isChineseText(text: string): boolean {
|
|
const chineseRegex = /^[\u4e00-\u9fff]+$/;
|
|
return chineseRegex.test(text);
|
|
},
|
|
splitToSingleChars(text: string): string[] {
|
|
const chineseRegex = /[\u4e00-\u9fff]/g;
|
|
const matches = text.match(chineseRegex);
|
|
return matches || [];
|
|
},
|
|
|
|
// 田字格
|
|
/* initGrid() {
|
|
const { rows, cols } = this.data as any;
|
|
const rowsArray = Array.from({ length: rows }, (_, i) => i);
|
|
const colsArray = Array.from({ length: cols }, (_, i) => i);
|
|
console.log('rowsArray----:', rowsArray)
|
|
console.log('colsArray----:', colsArray)
|
|
this.setData({ rowsArray, colsArray });
|
|
}, */
|
|
|
|
setCanvasBoxSize() {
|
|
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.setData({ boxWidth, boxHeight });
|
|
}
|
|
})
|
|
.exec();
|
|
},
|
|
initCanvas() {
|
|
// 然后初始化canvas
|
|
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;
|
|
this.wordDrawService = new WordDrawService(canvas, ctx, {
|
|
appName: '涂鸦丫小程序',
|
|
appHint: '练字|识字|打印',
|
|
title: '田字格 练 字 贴',
|
|
subTitle: '按笔画临摹练习'
|
|
});
|
|
this.drawPracticeSheet().catch(console.error);
|
|
}
|
|
}
|
|
});
|
|
},
|
|
|
|
// 绘制练字贴
|
|
async drawPracticeSheet() {
|
|
if (!this.canvas || !this.wordDrawService) {
|
|
this.initCanvas();
|
|
}
|
|
const { words } = this.data as any;
|
|
if (!words || words.length === 0) {
|
|
return;
|
|
}
|
|
|
|
// 构建汉字笔画数据
|
|
const wordsMap: Record<string, string[]> = {};
|
|
console.log('this.svgWords----:', this.svgWords)
|
|
words.forEach((word: string) => {
|
|
if (this.svgWords[word]) {
|
|
wordsMap[word] = this.svgWords[word];
|
|
}
|
|
});
|
|
if (Object.keys(wordsMap).length === 0) {
|
|
wx.showToast({ title: '暂不支持这些汉字', icon: 'none' });
|
|
return;
|
|
}
|
|
|
|
await this.wordDrawService?.draw(wordsMap);
|
|
},
|
|
|
|
// 下载打印练字贴
|
|
exportToPrint() {
|
|
const { words } = this.data as any;
|
|
if (!this.canvas || words.length <= 0) {
|
|
wx.showToast({ title: '请先生成练字贴', icon: 'none' });
|
|
return;
|
|
}
|
|
checkAndSaveImage(this.canvas);
|
|
},
|
|
|
|
// 分享功能
|
|
onShareAppMessage() {
|
|
return {
|
|
title: '涂鸦丫-练字|识字|打印',
|
|
path: '/pages/copyBook/index',
|
|
};
|
|
},
|
|
|
|
onShareTimeline() {
|
|
return {
|
|
title: '涂鸦丫-练字|识字|打印',
|
|
query: '/pages/copyBook/index',
|
|
};
|
|
},
|
|
});
|
|
|
|
|