feat: 重新调整header
This commit is contained in:
@@ -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 为 alphabetic,y 对应字母基线(类似左下角)
|
||||
*
|
||||
* */
|
||||
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;
|
||||
@@ -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;
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user