feat: 完成绘制汉字基础功能
This commit is contained in:
@@ -0,0 +1,223 @@
|
||||
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',
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user