feat: 重新调整header

This commit is contained in:
zhangyi
2025-03-28 18:09:41 +08:00
parent 40e6241f26
commit 2d686a9c01
4 changed files with 258 additions and 25 deletions
+1 -5
View File
@@ -1,4 +1,5 @@
import { PAPER_SIZE } from './constant';
import { getMiniCodeImagePath } from './utils';
class TextDrawService {
canvas: WechatMiniprogram.Canvas;
@@ -33,11 +34,6 @@ class TextDrawService {
}
drawHeader() {
const { canvas, ctx } = this;
const { appName, appHint, title, subTitle } = this.options;
}
drawHeader2() {
const { canvas, ctx } = this;
const { title } = this.options;
@@ -0,0 +1,239 @@
// import { PAPER_SIZE } from './constant';
import { getMiniCodeImage } from './utils';
class TextDrawService {
canvas: WechatMiniprogram.Canvas;
ctx: RenderingContext;
options: Record<string, any>;
paperSize: PaperSize;
currentX: number;
currentY: number;
constructor(canvas: Canvas, ctx: RenderingContext, options?: Record<string, any>) {
this.canvas = canvas;
this.ctx = ctx;
this.paperSize = 'A4';
this.options = {
appName: '涂鸦呀',
appHint: '涂色|识字|画画|认知',
title: '找一找 涂 色',
subTitle: '把相同的文字涂上相同的颜色',
radius: 36,
colors: ['#2196F3', '#FFEB3B', '#FF9800', '#F44336', '#F44336'],
characters: ['鱼', '鸟', '猫', '狗', '牛'],
...options,
};
this.currentX = 0;
this.currentY = 0;
}
draw() {
this.setPaper();
this.setPaper3();
this.drawHeader();
// this.drawLegend();
}
async drawHeader() {
const { canvas, ctx } = this;
const { appName, appHint, title, subTitle } = this.options;
this.currentX = 60;
this.currentY = 60;
const titleX = this.currentX + 140 + 14;
const titleY = 87;
const image = await getMiniCodeImage(canvas);
ctx.drawImage(image, 60, 60, 140, 140);
ctx.font = 'bold 36px "Microsoft Yahei"';
ctx.fillStyle = '#000';
ctx.textAlign = 'left';
ctx.textBaseline = 'top';
ctx.fillText(appName, titleX, titleY);
ctx.font = '24px "Microsoft Yahei"';
ctx.fillStyle = '#666';
ctx.fillText(appHint, titleX, 163);
// 绘制分割线
ctx.strokeStyle = '#888';
ctx.lineWidth = 2;
ctx.beginPath();
ctx.moveTo(483, 70);
ctx.lineTo(483, 70 + 140);
ctx.stroke();
ctx.font = 'bold 36px "Microsoft Yahei"';
ctx.fillStyle = '#000';
ctx.fillText(title, 538, titleY);
ctx.font = '24px "Microsoft Yahei"';
ctx.fillStyle = '#666';
ctx.fillText(subTitle, 538, 163);
this.drawLegend();
}
/** 绘制示例
* 矩形: x、y为左上角
* 圆形:x、y为圆心
* 文字:x textAlign 为 start,文本左边缘对齐
* y textBaseline 为 alphabeticy 对应字母基线(类似左下角)
*
* */
drawLegend() {
const { canvas, ctx, options } = this;
const { colors, characters, radius } = options;
const rectWidth = 100;
const rectHeight = 48;
const startX = 978;
const startY = 60 + radius; // 设置起始Y坐标
const len = characters.length || 4;
const canvasWidth = canvas.width;
/** 计算每个圆之间的间距 俩个60,一个是页面右侧边距,另一个是圆离右边距地边距*/
const spaceWidth = (canvasWidth - startX - 60 - 60 - radius * (len - 1)) / (len - 1);
ctx.moveTo(startX, startY);
colors.forEach((color: string, index: number) => {
const x = startX + index * (spaceWidth + radius);
const y = startY; // 计算圆的Y坐标
// 绘制圆
ctx.strokeStyle = '#333';
ctx.fillStyle = color;
ctx.lineWidth = 2;
ctx.beginPath();
ctx.arc(x, y, radius, 0, Math.PI * 2);
ctx.fill();
ctx.stroke();
ctx.closePath();
// 绘制长方形
ctx.fillStyle = '#fff'; // 长方形背景色
ctx.strokeStyle = '#333';
ctx.lineWidth = 2;
const rectangleX = x - rectWidth / 2; // 从圆形移动一半的长方形的长
const rectangleY = y + radius + 18; // 从圆形下移一个半径,再加上18的间距
ctx.strokeRect(rectangleX, rectangleY, rectWidth, rectHeight); // 绘制长方形
// 绘制字符
ctx.fillStyle = '#333';
ctx.font = 'bold 24px "Microsoft Yahei"';
ctx.textBaseline = 'top';
ctx.fillText(characters[index], rectangleX + 38, 163);
});
this.currentY = 220; // 计算分割线的Y坐标,距离示例图20px
this.drawLine(this.currentY);
}
drawLine(linY: number) {
const { canvas, ctx } = this;
ctx.strokeStyle = '#333';
ctx.lineWidth = 2;
ctx.beginPath();
ctx.moveTo(20, linY);
ctx.lineTo(canvas.width - 20, linY);
ctx.stroke();
}
setPaper() {
const { ctx, canvas } = this;
const { pixelRatio: dpr } = wx.getWindowInfo();
const { width, height } = { width: 595 * dpr, height: 842 * 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);
}
setPaper3() {
const { ctx, canvas } = this;
const { pixelRatio: dpr } = wx.getWindowInfo();
// @ts-ignore
const winWidth = canvas._width;
// @ts-ignore
const winHeight = canvas._height; // 容器逻辑尺寸
// 计算适配后的物理尺寸
const targetWidth = winWidth * dpr; // 宽度100%适配容器
const aspectRatio = 842 / 595; // 原图宽高比(示例为A4纸比例)
let targetHeight = targetWidth * aspectRatio; // 按比例计算高度
// 判断是否需要裁剪高度
if (targetHeight > winHeight * dpr) {
targetHeight = winHeight * dpr; // 若超出容器高度则强制裁剪
}
// 设置 Canvas 物理像素
canvas.width = targetWidth;
canvas.height = targetHeight;
console.log('targetWidth---:', targetWidth);
console.log('targetHeight---:', targetHeight);
this.clear();
ctx.fillStyle = '#fff'; // 设置背景色为白色
ctx.fillRect(0, 0, targetWidth, targetHeight);
}
setPaper2() {
const { canvas, ctx } = this;
const { pixelRatio: dpr } = wx.getWindowInfo();
const { width, height } = { width: 595 * dpr, height: 842 * dpr };
// @ts-ignore
const winWidth = canvas._width;
// @ts-ignore
const winHeight = canvas._height;
const canvasAspect = width / height; // Canvas 内容的宽高比
const containerAspect = winHeight / winWidth; // 容器的宽高比
// 选择缩放比例较小的方向(确保内容完全显示)
let scaleRatio =
containerAspect > canvasAspect
? winWidth / width // 以宽度为基准
: winHeight / height; // 以高度为基准
console.log('scaleRatio-----:', scaleRatio);
const scaledWidth = width * scaleRatio;
const scaledHeight = height * scaleRatio;
// 避免超过小程序画布最大限制(4096)
if (scaledWidth > 4096 || scaledHeight > 4096) {
scaleRatio *= Math.min(4096 / scaledWidth, 4096 / scaledHeight);
}
console.log('scaledWidth-----:', scaledWidth);
console.log('scaledHeight-----:', scaledHeight);
canvas.width = scaledWidth;
canvas.height = scaledHeight;
ctx.translate((winWidth * dpr) / 2, (winHeight * dpr) / 2);
ctx.scale(scaleRatio * dpr, scaleRatio * dpr);
ctx.translate(-width / 2, -height / 2); // 将内容原点移至中心
// this.canvas.width = width;
// this.canvas.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;
+12 -15
View File
@@ -16,22 +16,19 @@ export function setCanvasSize(canvas: Canvas, paperSize: PaperSize) {
return canvas;
}
export async function getMiniCodeImagePath() {
return getImagePath('/assets/imgs/mini-code.jpg');
export async function getMiniCodeImage(canvas: Canvas) {
return getImage(canvas, '/assets/imgs/mini-code.jpg');
}
export async function getImagePath(path: string) {
return new Promise((resolve) => {
// 如果是网络图片,需配置downloadFile域名
wx.getImageInfo({
src: path, // 本地图片路径
success: (res) => {
resolve(res.path);
},
fail: (err) => {
console.error('图片加载失败:', err);
resolve(''); // 可设置默认占位图
},
});
export async function getImage(canvas: Canvas, path: string) {
return new Promise((resolve, reject) => {
const image = canvas.createImage();
image.onload = () => {
resolve(image);
};
image.onerror = () => {
reject('图片加载异常');
};
image.src = path;
});
}