feat: 文本绘制测试页面

This commit is contained in:
zhangyi
2025-03-19 17:51:43 +08:00
parent d6fbf1a6d3
commit adb2652272
12 changed files with 169 additions and 75 deletions
+17 -1
View File
@@ -2,5 +2,21 @@
"singleQuote": true, "singleQuote": true,
"trailingComma": "all", "trailingComma": "all",
"tabWidth": 4, "tabWidth": 4,
"printWidth": 200 "printWidth": 100,
"formatOnSave": true,
"bracketSameLine": true,
"overrides": [
{
"files": "*.wxml",
"options": { "parser": "html" }
},
{
"files": "*.wxss",
"options": { "parser": "css" }
},
{
"files": "*.wxs",
"options": { "parser": "babel" }
}
]
} }
+7 -5
View File
@@ -1,9 +1,11 @@
{ {
"pages": ["pages/index/index", "pages/logs/logs", "demoPages/textPaint/textPaint"], "pages": [
"window": { "pages/index/index",
"navigationBarTextStyle": "black", "pages/logs/logs",
"navigationStyle": "custom" "demoPages/textPaint/textPaint",
}, "demoPages/textPaint2/textPaint"
],
"window": {},
"style": "v2", "style": "v2",
"rendererOptions": { "rendererOptions": {
"skyline": { "skyline": {
+9 -9
View File
@@ -1,10 +1,10 @@
/**app.wxss**/ /**app.wxss**/
.container { // .container {
height: 100%; // height: 100%;
display: flex; // display: flex;
flex-direction: column; // flex-direction: column;
align-items: center; // align-items: center;
justify-content: space-between; // justify-content: space-between;
padding: 200rpx 0; // padding: 200rpx 0;
box-sizing: border-box; // box-sizing: border-box;
} // }
-2
View File
@@ -22,7 +22,5 @@ App<IAppOption>({
// 发送 res.code 到后台换取 openId, sessionKey, unionId // 发送 res.code 到后台换取 openId, sessionKey, unionId
}, },
}); });
const a = '123';
}, },
}); });
+34 -17
View File
@@ -1,20 +1,37 @@
.color-picker { // .color-picker {
display: flex; // display: flex;
justify-content: center; // justify-content: center;
padding: 20rpx; // padding: 20rpx;
// }
// .color-circle {
// width: 80rpx;
// height: 80rpx;
// border-radius: 50%;
// margin: 0 40rpx;
// border: 4rpx solid #333;
// }
// .action-btn {
// width: 60%;
// background: #4CAF50;
// color: white;
// margin: 40rpx auto;
// }
.container {
height: 100vh;
background-color: transparent;
// overflow-y: hidden;
} }
.color-circle { .canvas-container {
width: 80rpx; margin: 20rpx;
height: 80rpx; width: calc(100% - 40rpx);
border-radius: 50%; // width: 100%;
margin: 0 40rpx; height: 86%;
border: 4rpx solid #333; // height: calc(100% - 80rpx);
} border: 1rpx solid #333;
background-color: #fff;
.action-btn { box-sizing: border-box;
width: 60%;
background: #4CAF50;
color: white;
margin: 40rpx auto;
} }
+65 -30
View File
@@ -3,20 +3,21 @@ Page({
ctx: null as RenderingContext | null, ctx: null as RenderingContext | null,
data: { data: {
characters: ['鱼', '鸟', '牛', '羊'] as const, // 固定汉字类型 characters: ['鱼', '鸟', '牛', '羊'] as const, // 固定汉字类型
colorMap: new Map([ colorMap: {
// 颜色映射关系 : '#2196F3', // 蓝色
['鱼', '#2196F3'], // : '#FFEB3B', //
['鸟', '#FFEB3B'], // : '#FF9800', //
['牛', '#FF9800'], // : '#9C27B0', //
['羊', '#9C27B0'], // 紫色 } as Record<string, string>,
]),
matrix: [] as string[], // 随机汉字矩阵 matrix: [] as string[], // 随机汉字矩阵
selectedColor: '', // 当前选中颜色 selectedColor: '', // 当前选中颜色
selectedChar: '', // 当前选中汉字 selectedChar: '', // 当前选中汉字
}, },
onLoad() { onLoad() {
console.log('textPaint2 onLoad');
this.generateMatrix(); this.generateMatrix();
this.initCanvas();
}, },
// 生成6列随机矩阵 // 生成6列随机矩阵
@@ -33,36 +34,59 @@ Page({
// 初始化A4画布(300DPI // 初始化A4画布(300DPI
initCanvas() { initCanvas() {
const dpi = 300;
const width = 2480,
height = 3508; // A4精确像素
wx.createSelectorQuery() wx.createSelectorQuery()
.select('#canvas') .select('#textCanvas')
.node() .fields({
node: true,
size: true,
})
.exec((res) => { .exec((res) => {
const canvas = res[0].node; const canvas = res[0].node;
this.canvas = canvas;
const ctx = canvas.getContext('2d'); const ctx = canvas.getContext('2d');
this.canvas = canvas;
this.ctx = ctx; this.ctx = ctx;
this.setCanvasSize(canvas, ctx);
// 设置物理尺寸 // ctx.fillRect(0, 0, 2480, 3508);
canvas.width = width;
canvas.height = height;
// 适配屏幕显示
const ratio = wx.getWindowInfo().pixelRatio;
canvas.style.width = `${width / ratio}px`;
ctx.scale(ratio, ratio);
this.drawGameBoard(ctx); this.drawGameBoard(ctx);
}); });
}, },
setCanvasSize(canvas: Canvas, ctx: RenderingContext) {
const A4 = {
width: 2480,
height: 3508,
};
const { pixelRatio: dpr, windowWidth, windowHeight } = wx.getWindowInfo();
// const printWidth = A4.width;
// const printHeight = A4.height;
// @ts-ignore
const originWidth = canvas._width || windowWidth;
// @ts-ignore
const originHeight = canvas._height || windowHeight;
console.log('originWidth---:', originWidth);
console.log('originHeight---:', originHeight);
canvas.width = A4.width;
canvas.height = A4.height;
console.log('canvas----:', canvas);
// 计算显示比例
// const scaleRatio = Math.min(originWidth / printWidth, originHeight / printHeight);
// console.log('scaleRatio---:', scaleRatio);
// console.log('dpr---:', dpr);
// 设置坐标系
// ctx.scale(scaleRatio * dpr, scaleRatio * dpr);
},
// 绘制完整游戏界面 // 绘制完整游戏界面
drawGameBoard(ctx?: RenderingContext) { drawGameBoard(ctx?: RenderingContext) {
const canvas = this.canvas as Canvas;
ctx = ctx || (this.ctx as RenderingContext); ctx = ctx || (this.ctx as RenderingContext);
ctx.clearRect(0, 0, 2480, 3508); ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = '#333'; // 设置填充色为白色
ctx.fillRect(0, 0, 2480, 3508); // 覆盖整个A4画布
// 绘制标题 // 绘制标题
ctx.font = 'bold 80px "Microsoft Yahei"'; ctx.font = 'bold 80px "Microsoft Yahei"';
@@ -78,11 +102,12 @@ Page({
// 绘制颜色示例 // 绘制颜色示例
drawColorLegend(ctx: RenderingContext, y: number) { drawColorLegend(ctx: RenderingContext, y: number) {
console.log('this.data:', this.data);
let x = 500; let x = 500;
this.data.characters.forEach((char) => { this.data.characters.forEach((char) => {
ctx.beginPath(); ctx.beginPath();
ctx.arc(x, y, 50, 0, Math.PI * 2); ctx.arc(x, y, 50, 0, Math.PI * 2);
ctx.fillStyle = this.data.colorMap.get(char) as string; ctx.fillStyle = this.data.colorMap[char] as string;
ctx.fill(); ctx.fill();
ctx.strokeStyle = '#333'; ctx.strokeStyle = '#333';
ctx.lineWidth = 4; ctx.lineWidth = 4;
@@ -95,8 +120,10 @@ Page({
drawCharacterMatrix(ctx: RenderingContext, startY: number) { drawCharacterMatrix(ctx: RenderingContext, startY: number) {
const cols = 6; const cols = 6;
const cellSize = 350; // 每个单元格大小 const cellSize = 350; // 每个单元格大小
const colorMap = this.data.colorMap;
this.data.matrix.forEach((char, index) => { this.data.matrix.forEach((char: string, index) => {
char = char || '';
const row = Math.floor(index / cols); const row = Math.floor(index / cols);
const col = index % cols; const col = index % cols;
@@ -115,7 +142,7 @@ Page({
// 绘制汉字 // 绘制汉字
ctx.font = 'bold 100px "Microsoft Yahei"'; ctx.font = 'bold 100px "Microsoft Yahei"';
ctx.fillStyle = this.data.colorMap.get(char) || ''; ctx.fillStyle = (colorMap[char] as string) || '';
ctx.textAlign = 'center'; ctx.textAlign = 'center';
ctx.textBaseline = 'middle'; ctx.textBaseline = 'middle';
ctx.fillText(char, x, y); ctx.fillText(char, x, y);
@@ -127,7 +154,7 @@ Page({
const index = e.currentTarget.dataset.index; const index = e.currentTarget.dataset.index;
const selectedChar = this.data.characters[index]; const selectedChar = this.data.characters[index];
this.setData({ this.setData({
selectedColor: this.data.colorMap.get(selectedChar), selectedColor: this.data.colorMap[selectedChar],
selectedChar, selectedChar,
}); });
}, },
@@ -137,7 +164,9 @@ Page({
const index = e.currentTarget.dataset.index; const index = e.currentTarget.dataset.index;
if (!this.data.selectedColor) return; if (!this.data.selectedColor) return;
const matrix = this.data.matrix.map((char, i) => (i === index ? this.data.selectedChar : char)); const matrix = this.data.matrix.map((char, i) =>
i === index ? this.data.selectedChar : char,
);
this.setData({ matrix }, () => { this.setData({ matrix }, () => {
this.drawGameBoard(); this.drawGameBoard();
@@ -146,12 +175,18 @@ Page({
// 导出A4图片 // 导出A4图片
exportToPrint() { exportToPrint() {
console.log('this.canvas:', this.canvas);
if (this.canvas) { if (this.canvas) {
wx.canvasToTempFilePath({ wx.canvasToTempFilePath({
canvas: this.canvas, canvas: this.canvas,
fileType: 'png', fileType: 'png',
quality: 1, quality: 1,
success: (res) => { success: (res) => {
wx.getImageInfo({
src: res.tempFilePath,
success: (res) =>
console.log('getImageInfo image size :', res.width, res.height), // 应输出2480x3508
});
wx.saveImageToPhotosAlbum({ wx.saveImageToPhotosAlbum({
filePath: res.tempFilePath, filePath: res.tempFilePath,
success: () => wx.showToast({ title: '保存成功' }), success: () => wx.showToast({ title: '保存成功' }),
@@ -1,6 +1,6 @@
<view class="container"> <view class="container">
<!-- 颜色选择区 --> <!-- 颜色选择区 -->
<view class="color-picker"> <!-- <view class="color-picker">
<block wx:for="{{characters}}" wx:key="index"> <block wx:for="{{characters}}" wx:key="index">
<view <view
class="color-circle" class="color-circle"
@@ -8,10 +8,10 @@
bindtap="handleColorSelect" bindtap="handleColorSelect"
data-index="{{index}}"></view> data-index="{{index}}"></view>
</block> </block>
</view> </view> -->
<!-- 画布容器 --> <!-- 画布容器 -->
<canvas type="2d" id="canvas" style="width: 100%; height: 80vh" /> <canvas type="2d" id="textCanvas" class="canvas-container" />
<!-- 操作按钮 --> <!-- 操作按钮 -->
<button class="action-btn" bindtap="exportToPrint">导出A4图片</button> <button class="action-btn" bindtap="exportToPrint">导出A4图片</button>
+8 -2
View File
@@ -8,8 +8,8 @@ Page({
}, },
{ {
key: 1, key: 1,
title: '文本绘制', title: '文本绘制2',
url: '/demoPages/textPaint/textPaint', url: '/demoPages/textPaint2/textPaint',
}, },
{ {
key: 2, key: 2,
@@ -23,4 +23,10 @@ Page({
}, },
], ],
}, },
tapCard(e: WechatMiniprogram.TouchEvent) {
const { url } = e.currentTarget.dataset;
console.log('navigateTo url:', url);
wx.navigateTo({ url });
},
}); });
+3 -2
View File
@@ -2,9 +2,10 @@
<scroll-view class="scroll-view" scroll-y type="list"> <scroll-view class="scroll-view" scroll-y type="list">
<view <view
class="card" class="card"
x:for="{{cards}}" wx:for="{{cards}}"
wx:for-item="card" wx:for-item="card"
bindtap="tabCard" wx:key="*this"
bindtap="tapCard"
data-url="{{card.url}}"> data-url="{{card.url}}">
<view class="card-title">{{card.title}}</view> <view class="card-title">{{card.title}}</view>
</view> </view>
+2 -2
View File
@@ -18,7 +18,7 @@
"postcss": false, "postcss": false,
"minified": true, "minified": true,
"minifyWXSS": true, "minifyWXSS": true,
"enhance": true, "enhance": false,
"showShadowRootInWxmlPanel": false, "showShadowRootInWxmlPanel": false,
"packNpmRelationList": [ "packNpmRelationList": [
{ {
@@ -29,7 +29,7 @@
"ignoreUploadUnusedFiles": true, "ignoreUploadUnusedFiles": true,
"compileHotReLoad": false, "compileHotReLoad": false,
"skylineRenderEnable": true, "skylineRenderEnable": true,
"es6": true, "es6": false,
"packNpmManually": true "packNpmManually": true
}, },
"simulatorType": "wechat", "simulatorType": "wechat",
+19 -1
View File
@@ -4,5 +4,23 @@
"setting": { "setting": {
"compileHotReLoad": true "compileHotReLoad": true
}, },
"libVersion": "2.32.3" "libVersion": "3.7.10",
"condition": {
"miniprogram": {
"list": [
{
"name": "textPaint2",
"pathName": "demoPages/textPaint2/textPaint",
"query": "",
"launchMode": "default",
"scene": null
},
{
"name": "db guide",
"pathName": "pages/databaseGuide/databaseGuide",
"query": ""
}
]
}
}
} }
+2 -1
View File
@@ -1,3 +1,4 @@
// 全局声明 // 全局声明
type Canvas = WechatMiniprogram.Canvas; type Canvas = WechatMiniprogram.Canvas;
type RenderingContext = WechatMiniprogram.CanvasRenderingContext; type RenderingContext = WechatMiniprogram.CanvasRenderingContext2D;
type TouchEvent = WechatMiniprogram.TouchEvent;