diff --git a/miniprogram/app.json b/miniprogram/app.json index 28953aa..2bec5a4 100644 --- a/miniprogram/app.json +++ b/miniprogram/app.json @@ -1,7 +1,6 @@ { "pages": [ "pages/index/index", - "pages/logs/logs", "demoPages/textPaint/textPaint", "demoPages/textPaint2/textPaint" ], diff --git a/miniprogram/canvasService/constant.ts b/miniprogram/canvasService/constant.ts index aa152b1..4858c35 100644 --- a/miniprogram/canvasService/constant.ts +++ b/miniprogram/canvasService/constant.ts @@ -1,7 +1,9 @@ const PAPER_SIZE = { A4: { - width: 2480, - height: 3508, + // width: 2480, + // height: 3508, + width: 595, + height: 842, }, A3: { width: 3508, diff --git a/miniprogram/canvasService/textDrawServiceV2.ts b/miniprogram/canvasService/textDrawServiceV2.ts index 988ff27..8730789 100644 --- a/miniprogram/canvasService/textDrawServiceV2.ts +++ b/miniprogram/canvasService/textDrawServiceV2.ts @@ -29,7 +29,7 @@ class TextDrawService { draw() { this.setPaper(); - this.setPaper3(); + // this.setPaper3(); this.drawHeader(); // this.drawLegend(); } diff --git a/miniprogram/canvasService/textDrawServiceV3.ts b/miniprogram/canvasService/textDrawServiceV3.ts new file mode 100644 index 0000000..61bb783 --- /dev/null +++ b/miniprogram/canvasService/textDrawServiceV3.ts @@ -0,0 +1,220 @@ +// import { PAPER_SIZE } from './constant'; +import { PAPER_SIZE } from './constant'; +import { getMiniCodeImage } from './utils'; + +class TextDrawService { + canvas: WechatMiniprogram.Canvas; + ctx: RenderingContext; + options: Record; + paperSize: PaperSize; + currentX: number; + currentY: number; + + constructor(canvas: Canvas, ctx: RenderingContext, options?: Record) { + this.canvas = canvas; + this.ctx = ctx; + this.paperSize = 'A4'; + this.options = { + appName: '涂鸦呀', + appHint: '涂色|识字|画画|认知', + title: '找一找 涂 色', + subTitle: '把相同的文字涂上相同的颜色', + colors: ['#FF0000', '#FDAF1A', '#0057FC', '#09FF00', '#8D00FF'], + characters: ['文', '升', '国', '舟', '丹'], + ...options, + }; + this.currentX = 0; + this.currentY = 0; + } + + draw() { + this.setPaper(); + this.drawHeader(); + this.drawLegend(); + this.drawContent(); + } + + async drawHeader() { + const { canvas, ctx } = this; + const { appName, appHint, title, subTitle } = this.options; + + this.currentX = 80; + this.currentY = 80; + const titleX = this.currentX + 200 + 48; + const titleY = 80; + const image = await getMiniCodeImage(canvas); + ctx.drawImage(image, 80, 80, 200, 200); + + ctx.font = 'bold 64px "Microsoft Yahei"'; + ctx.fillStyle = '#000'; + ctx.textAlign = 'left'; + ctx.textBaseline = 'top'; + + ctx.fillText(appName, titleX, titleY); + + ctx.font = '48px "Microsoft Yahei"'; + ctx.fillStyle = '#666'; + ctx.fillText(appHint, titleX, 186); + + // 绘制分割线 + // ctx.strokeStyle = '#888'; + // ctx.lineWidth = 2; + // ctx.beginPath(); + // ctx.moveTo(483, 70); + // ctx.lineTo(483, 70 + 140); + // ctx.stroke(); + + ctx.font = 'bold 64px "Microsoft Yahei"'; + ctx.fillStyle = '#000'; + ctx.fillText(title, 1015, titleY); + + ctx.font = '48px "Microsoft Yahei"'; + ctx.fillStyle = '#666'; + ctx.fillText(subTitle, 1015, 186); + + this.currentY = 304; + this.drawLine(this.currentY); + } + + /** 绘制示例 + * 矩形: x、y为左上角 + * 圆形:x、y为圆心 + * 文字:x textAlign 为 start,文本左边缘对齐 + * y textBaseline 为 alphabetic,y 对应字母基线(类似左下角) + * + * */ + drawLegend() { + const { canvas, ctx, options } = this; + const { colors, characters } = options; + const radius = 65; + const rectWidth = 180; + const rectHeight = 80; + const startX = 260 + radius; // 圆形的X坐标是圆心 + const startY = 304 + 26 + radius; // 圆形的Y坐标是圆心 + const len = characters.length || 4; + const canvasWidth = canvas.width; + /** 计算每个圆之间的间距 俩个60,一个是页面右侧边距,另一个是圆离右边距地边距*/ + const spaceWidth = (canvasWidth - startX * 2) / (len - 1); + + ctx.moveTo(startX, startY); + colors.forEach((color: string, index: number) => { + const x = startX + index * spaceWidth; + const y = startY; // 计算圆的Y坐标 + + // 绘制圆 + ctx.strokeStyle = '#000'; + ctx.fillStyle = color; + ctx.lineWidth = 4; + ctx.beginPath(); + ctx.arc(x, y, radius, 0, Math.PI * 2); + ctx.fill(); + ctx.stroke(); + ctx.closePath(); + + // 绘制长方形 + ctx.fillStyle = '#fff'; // 长方形背景色 + ctx.strokeStyle = '#000'; + ctx.lineWidth = 4; + const rectangleX = x - rectWidth / 2; // 从圆形移动一半的长方形的长 + const rectangleY = y + radius + 43; // 从圆形下移一个半径,再加上43的间距 + ctx.strokeRect(rectangleX, rectangleY, rectWidth, rectHeight); // 绘制长方形 + + // 绘制字符 + ctx.fillStyle = '#333'; + ctx.font = 'bold 48px "Microsoft Yahei"'; + ctx.textBaseline = 'middle'; + ctx.textAlign = 'center'; + ctx.fillText( + characters[index], + rectangleX + rectWidth / 2, + rectangleY + rectHeight / 2, + rectWidth, + ); + }); + + this.currentY = 612; // 计算分割线的Y坐标,距离示例图20px + this.drawLine(this.currentY); + } + + drawContent() { + const { canvas, ctx, options } = this; + const { characters } = options; + + const len = characters.length; + const rows = 8; + const radius = 80; + const fontSize = 72; + + const startY = this.currentY + 62 + radius; + const startX1 = 310 + radius; + const startX2 = 200 + radius; + const canvasWidth = canvas.width; + const spaceWidthFrist = (canvasWidth - startX1 * 2) / (5 - 1); + const spaceWidthSecond = (canvasWidth - startX2 * 2) / (6 - 1); + const spaceHeight = 54; + + ctx.moveTo(startX1, startY); + for (let i = 0; i < rows; i++) { + const cols = i % 2 === 0 ? 5 : 6; + + for (let j = 0; j < cols; j++) { + const y = startY + i * (spaceHeight + radius * 2); + const x = + i % 2 === 0 ? startX1 + j * spaceWidthFrist : startX2 + j * spaceWidthSecond; + + const character = characters[Math.floor(Math.random() * len)]; + + ctx.fillStyle = '#fff'; + ctx.strokeStyle = '#000'; + ctx.lineWidth = 4; + ctx.beginPath(); + ctx.arc(x, y, radius, 0, Math.PI * 2); + ctx.fill(); + ctx.stroke(); + ctx.closePath(); + + ctx.fillStyle = '#333'; + ctx.font = `${fontSize}px "Microsoft Yahei"`; + ctx.textBaseline = 'middle'; + ctx.textAlign = 'center'; + ctx.fillText(character, x, y, radius * 2); + } + } + } + + drawLine(linY: number) { + const { canvas, ctx } = this; + + ctx.strokeStyle = '#000'; + ctx.lineWidth = 2; + ctx.beginPath(); + ctx.moveTo(80, linY); + ctx.lineTo(canvas.width - 80, linY); + ctx.stroke(); + } + + setPaper() { + const { ctx, canvas } = this; + const { pixelRatio: dpr } = wx.getWindowInfo(); + // const { width, height } = { width: 595 * dpr, height: 842 * dpr }; + let { width, height } = PAPER_SIZE[this.paperSize]; + width = width * dpr; + height = height * dpr; + + canvas.width = width; + canvas.height = height; + + console.log('width---:', width); + console.log('height---:', height); + this.clear(); + ctx.fillStyle = '#fff'; // 设置背景色为白色 + ctx.fillRect(0, 0, width, height); + } + + clear() { + const canvas = this.canvas; + this.ctx.clearRect(0, 0, canvas.width, canvas.height); + } +} + +export default TextDrawService; diff --git a/miniprogram/demoPages/textPaint2/textPaint.less b/miniprogram/demoPages/textPaint2/textPaint.less index 93bc016..7737f19 100644 --- a/miniprogram/demoPages/textPaint2/textPaint.less +++ b/miniprogram/demoPages/textPaint2/textPaint.less @@ -22,16 +22,20 @@ .container { height: 100vh; background-color: transparent; - // overflow-y: hidden; + background-color: transparent; + display: flex; + align-items: center; + flex-direction: column; } .canvas-container { - margin: 20rpx; - width: calc(100% - 40rpx); - // width: 100%; - height: 86%; + margin-top: 20rpx; + // margin: 20rpx; + // width: calc(100% - 40rpx); + // // width: 100%; + // height: 580px; // height: calc(100% - 80rpx); - border: 1rpx solid #333; + border: 2rpx solid #333; background-color: #fff; box-sizing: border-box; -} \ No newline at end of file +} diff --git a/miniprogram/demoPages/textPaint2/textPaint.ts b/miniprogram/demoPages/textPaint2/textPaint.ts index f7bf0f7..da770e6 100644 --- a/miniprogram/demoPages/textPaint2/textPaint.ts +++ b/miniprogram/demoPages/textPaint2/textPaint.ts @@ -1,5 +1,7 @@ // import TextDrawService from '../../canvasService/textDrawService'; -import TextDrawServiceV2 from '../../canvasService/textDrawServiceV2'; +// import TextDrawServiceV2 from '../../canvasService/textDrawServiceV2'; +import { PAPER_SIZE } from '../../canvasService/constant'; +import TextDrawServiceV3 from '../../canvasService/textDrawServiceV3'; Page({ canvas: null as Canvas | null, @@ -19,10 +21,49 @@ Page({ onLoad() { console.log('textPaint2 onLoad'); - this.generateMatrix(); - this.initCanvas(); + // this.setCanvasBoxSize(); + // this.generateMatrix(); }, + onReady() { + wx.nextTick(() => { + this.setCanvasBoxSize(); + }); + }, + + // setCanvasBoxSize() { + // const { width: paperWidth, height: paperHeight } = PAPER_SIZE['A4']; + + // // 逻辑尺寸(容器宽高) + // const boxWidth = windowWidth - 40; + // const boxHeight = boxWidth / (paperWidth / paperHeight); + // console.log('boxWidth---:', boxWidth); + // console.log('boxHeight---:', boxHeight); + // this.setData({ boxWidth, boxHeight }); + // // // 实际像素尺寸(需乘以设备像素比) + // // const canvasWidth = boxWidth * pixelRatio; + // // const canvasHeight = boxHeight * pixelRatio; + + // // // 更新 Canvas 节点属性 + // // const query = wx.createSelectorQuery().select('#textCanvas'); + // // query.fields({ node: true, size: true }).exec((res) => { + // // const canvas = res[0].node; + // // canvas.width = canvasWidth; + // // canvas.height = canvasHeight; + // // // 缩放上下文以适配逻辑尺寸 + // // const ctx = canvas.getContext('2d'); + // // ctx.scale(pixelRatio, pixelRatio); + + // // this.canvas = canvas; + // // this.ctx = ctx; + + // // const textDrawService = new TextDrawServiceV3(canvas, ctx); + // // textDrawService.draw(); + // // ctx.fillStyle = '#fff'; // 设置背景色为白色 + // // ctx.fillRect(0, 0, canvasWidth, canvasHeight); + // // }); + // }, + // 生成6列随机矩阵 generateMatrix() { const shuffled = [...this.data.characters] @@ -35,6 +76,18 @@ Page({ this.setData({ matrix: shuffled.slice(0, 42) }); // 6列x7行 }, + setCanvasBoxSize() { + const { width, height } = PAPER_SIZE['A4']; + const { windowWidth } = wx.getWindowInfo(); + const boxWidth = windowWidth - 20; + const boxHeight = boxWidth / (width / height); + console.log('boxWidth----:', boxWidth); + console.log('boxHeight----:', boxHeight); + this.setData({ boxHeight, boxWidth }, () => { + this.initCanvas(); + }); + }, + // 初始化A4画布(300DPI) initCanvas() { wx.createSelectorQuery() @@ -44,13 +97,35 @@ Page({ size: true, }) .exec((res) => { - const canvas = res[0].node; - const ctx = canvas.getContext('2d'); - this.canvas = canvas; - this.ctx = ctx; + 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]; + console.log('rect-----:', rect); + // const width = rect.width * dpr; + // const height = rect.height * dpr; - const textDrawService = new TextDrawServiceV2(canvas, ctx); - textDrawService.draw(); + // 设置canvas的实际尺寸 + // canvas.width = width; + // canvas.height = height; + // ctx.scale(dpr, dpr); + + // 使用TextDrawServiceV3绘制 + const textDrawService = new TextDrawServiceV3(canvas, ctx); + textDrawService.draw(); + } + } + + // const canvas = res[0].node; + // const ctx = canvas.getContext('2d'); + // this.canvas = canvas; + // this.ctx = ctx; + + // const textDrawService = new TextDrawServiceV3(canvas, ctx); + // textDrawService.draw(); // this.setCanvasSize(canvas, ctx); // ctx.fillRect(0, 0, 2480, 3508); diff --git a/miniprogram/demoPages/textPaint2/textPaint.wxml b/miniprogram/demoPages/textPaint2/textPaint.wxml index df1598a..cf16984 100644 --- a/miniprogram/demoPages/textPaint2/textPaint.wxml +++ b/miniprogram/demoPages/textPaint2/textPaint.wxml @@ -9,10 +9,9 @@ data-index="{{index}}"> --> - - - + + 当前宽度:{{boxWidth}}px,高度:{{boxHeight}}px - + \ No newline at end of file diff --git a/project.private.config.json b/project.private.config.json index 189d573..4f08148 100644 --- a/project.private.config.json +++ b/project.private.config.json @@ -4,7 +4,7 @@ "setting": { "compileHotReLoad": true }, - "libVersion": "3.7.10", + "libVersion": "3.7.12", "condition": { "miniprogram": { "list": [