feat:架构代码优化
This commit is contained in:
@@ -1,16 +1,10 @@
|
||||
// import { PAPER_SIZE } from './constant';
|
||||
import { PAPER_SIZE } from '../constants/colors';
|
||||
import {
|
||||
drawHeader as drawHeaderCommon,
|
||||
drawMiniHeader as drawMiniHeaderCommon,
|
||||
} from './headerDrawService';
|
||||
|
||||
import { BaseDrawService } from './baseDraw';
|
||||
/**
|
||||
* 计算示例区域圆的中心点
|
||||
* @param canvasWidth 画布宽度
|
||||
* @param canvasWidth 画布宽度(逻辑像素)
|
||||
* @param circleCount 圆的数量
|
||||
* @param padding 圆的间距
|
||||
* @param radius 圆的半径
|
||||
* @param padding 圆的间距(逻辑像素)
|
||||
* @param radius 圆的半径(逻辑像素)
|
||||
* @returns 圆的中心点
|
||||
*/
|
||||
function calculateCircleCenters(
|
||||
@@ -24,7 +18,6 @@ function calculateCircleCenters(
|
||||
const centers = [];
|
||||
|
||||
if (circleCount === 1) {
|
||||
// 单个圆圈直接居中
|
||||
centers.push(canvasWidth / 2);
|
||||
} else {
|
||||
const requiredSpace = 2 * radius * circleCount;
|
||||
@@ -32,7 +25,6 @@ function calculateCircleCenters(
|
||||
(availableWidth - requiredSpace) / (circleCount - 1);
|
||||
|
||||
if (spaceBetween > maxSpacing) {
|
||||
// 超过最大间距时,固定间距并居中对齐
|
||||
const totalWidth = 2 * radius + (circleCount - 1) * maxSpacing;
|
||||
const startX = (canvasWidth - totalWidth) / 2 + radius;
|
||||
|
||||
@@ -40,7 +32,6 @@ function calculateCircleCenters(
|
||||
centers.push(startX + i * maxSpacing);
|
||||
}
|
||||
} else {
|
||||
// 正常均匀分布
|
||||
const startX = padding + radius;
|
||||
|
||||
for (let i = 0; i < circleCount; i++) {
|
||||
@@ -52,14 +43,7 @@ function calculateCircleCenters(
|
||||
return centers;
|
||||
}
|
||||
|
||||
class TextDrawService {
|
||||
headerType: PrintHeader = 'wechat';
|
||||
canvas: WechatMiniprogram.Canvas;
|
||||
ctx: RenderingContext;
|
||||
options: Record<string, any>;
|
||||
paperSize: PaperSize;
|
||||
currentX: number;
|
||||
currentY: number;
|
||||
class TextDrawService extends BaseDrawService {
|
||||
colors: string[];
|
||||
characters: string[];
|
||||
|
||||
@@ -69,27 +53,13 @@ class TextDrawService {
|
||||
options?: Record<string, any>,
|
||||
) {
|
||||
options = options || {};
|
||||
this.canvas = canvas;
|
||||
this.ctx = ctx;
|
||||
this.paperSize = 'A4';
|
||||
this.options = {
|
||||
appName: '涂鸦丫小程序',
|
||||
appHint: '识字|识图|练字|打印',
|
||||
super(canvas, ctx, {
|
||||
title: '找一找 涂 色',
|
||||
subTitle: '给文字涂上相同的颜色',
|
||||
...options,
|
||||
};
|
||||
this.currentX = 0;
|
||||
this.currentY = 0;
|
||||
});
|
||||
this.colors = ['#000'];
|
||||
this.characters = ['王'];
|
||||
this.setPrintConfig();
|
||||
}
|
||||
|
||||
setPrintConfig() {
|
||||
const printConfig = getApp().getPrintConfig();
|
||||
this.headerType = printConfig.header;
|
||||
this.options.appName = printConfig.appName;
|
||||
}
|
||||
|
||||
async draw(list: Array<{ color: string; word: string }>) {
|
||||
@@ -99,82 +69,58 @@ class TextDrawService {
|
||||
this.characters = list.map((item) => item.word || '日');
|
||||
this.clear();
|
||||
this.setPaper();
|
||||
|
||||
// 绘制Header
|
||||
if (this.headerType !== 'minimal') {
|
||||
await this.drawHeader();
|
||||
} else {
|
||||
this.drawMiniHeader();
|
||||
await this.drawMiniHeader();
|
||||
}
|
||||
|
||||
this.drawDivider();
|
||||
this.drawLegend();
|
||||
this.drawContent();
|
||||
}
|
||||
|
||||
async drawHeader() {
|
||||
this.currentX = 80;
|
||||
this.currentY = 80;
|
||||
await drawHeaderCommon({
|
||||
canvas: this.canvas,
|
||||
ctx: this.ctx,
|
||||
headerType: this.headerType,
|
||||
options: {
|
||||
appName: this.options.appName || '涂鸦丫小程序',
|
||||
appHint: this.options.appHint || '识字|识图|练字|打印',
|
||||
title: this.options.title || '找一找 涂 色',
|
||||
subTitle: this.options.subTitle || '给文字涂上相同的颜色',
|
||||
},
|
||||
onHeaderDrawn: (currentY) => {
|
||||
this.currentY = currentY;
|
||||
this.drawLine(this.currentY);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
drawMiniHeader() {
|
||||
drawMiniHeaderCommon({
|
||||
canvas: this.canvas,
|
||||
ctx: this.ctx,
|
||||
options: {
|
||||
appName: this.options.appName || '涂鸦丫小程序',
|
||||
title: this.options.title || '找一找 涂 色',
|
||||
},
|
||||
onHeaderDrawn: (currentY) => {
|
||||
this.currentY = currentY;
|
||||
this.drawLine(this.currentY);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/** 绘制示例
|
||||
* 矩形: x、y为左上角
|
||||
* 圆形:x、y为圆心
|
||||
* 文字:x textAlign 为 start,文本左边缘对齐
|
||||
* y textBaseline 为 alphabetic,y 对应字母基线(类似左下角)
|
||||
*
|
||||
* 注意:所有尺寸已转换为逻辑像素(除以3)
|
||||
* */
|
||||
drawLegend() {
|
||||
const { canvas, ctx, colors, characters } = this;
|
||||
const { ctx, colors, characters } = this;
|
||||
if (characters.length <= 0) return;
|
||||
// const { colors, characters } = options;
|
||||
this.currentY = this.headerType === 'minimal' ? 200 : 304;
|
||||
const radius = 65;
|
||||
const rectWidth = 180;
|
||||
const rectHeight = 80;
|
||||
const startX = 260 + radius; // 圆形的X坐标是圆心
|
||||
const startY = this.currentY + 30 + radius; // 圆形的Y坐标是圆心
|
||||
|
||||
// 逻辑像素尺寸(原始尺寸除以3)
|
||||
this.currentY = this.headerType === 'minimal' ? 68 : 110; // 200/3≈67, 304/3≈101
|
||||
const radius = 22; // 65/3≈22
|
||||
const rectWidth = 60; // 180/3=60
|
||||
const rectHeight = 27; // 80/3≈27
|
||||
const startX = 87 + radius; // (260+65)/3≈108
|
||||
const startY = this.currentY + 10 + radius; // (30+65)/3≈32
|
||||
const len = characters.length || 4;
|
||||
const canvasWidth = canvas.width;
|
||||
const centers = calculateCircleCenters(canvasWidth, len, 220, 65);
|
||||
/** 计算每个圆之间的间距 俩个60,一个是页面右侧边距,另一个是圆离右边距地边距*/
|
||||
const spaceWidth = len > 3 ? (canvasWidth - startX * 2) / (len - 1) : 0;
|
||||
const centers = calculateCircleCenters(
|
||||
this.canvasWidth,
|
||||
len,
|
||||
73,
|
||||
radius,
|
||||
); // 220/3≈73
|
||||
|
||||
/** 计算每个圆之间的间距 */
|
||||
const spaceWidth =
|
||||
len > 3 ? (this.canvasWidth - startX * 2) / (len - 1) : 0;
|
||||
|
||||
ctx.moveTo(startX, startY);
|
||||
colors.forEach((color: string, index: number) => {
|
||||
const x = centers[index] || startX + index * spaceWidth; // 计算圆的X坐标
|
||||
const y = startY; // 计算圆的Y坐标
|
||||
const x = centers[index] || startX + index * spaceWidth;
|
||||
const y = startY;
|
||||
// 绘制圆
|
||||
ctx.strokeStyle = '#000';
|
||||
ctx.fillStyle = color;
|
||||
ctx.lineWidth = 4;
|
||||
ctx.lineWidth = 1; // 4/3≈1
|
||||
ctx.beginPath();
|
||||
ctx.arc(x, y, radius, 0, Math.PI * 2);
|
||||
ctx.fill();
|
||||
@@ -182,16 +128,16 @@ class TextDrawService {
|
||||
ctx.closePath();
|
||||
|
||||
// 绘制长方形
|
||||
ctx.fillStyle = '#fff'; // 长方形背景色
|
||||
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.lineWidth = 1; // 4/3≈1
|
||||
const rectangleX = x - rectWidth / 2;
|
||||
const rectangleY = y + radius + 14; // 43/3≈14
|
||||
ctx.strokeRect(rectangleX, rectangleY, rectWidth, rectHeight);
|
||||
|
||||
// 绘制字符
|
||||
ctx.fillStyle = '#333';
|
||||
ctx.font = 'bold 48px "Microsoft Yahei"';
|
||||
ctx.font = 'bold 16px "Microsoft Yahei"'; // 48/3=16
|
||||
ctx.textBaseline = 'middle';
|
||||
ctx.textAlign = 'center';
|
||||
ctx.fillText(
|
||||
@@ -202,26 +148,25 @@ class TextDrawService {
|
||||
);
|
||||
});
|
||||
|
||||
this.currentY = this.headerType === 'minimal' ? 522 : 612; // 计算分割线的Y坐标,距离示例图20px
|
||||
this.drawLine(this.currentY);
|
||||
this.currentY = this.headerType === 'minimal' ? 178 : 230; // 522/3=174, 612/3=204
|
||||
this.drawDivider();
|
||||
}
|
||||
|
||||
drawContent() {
|
||||
const { canvas, ctx, characters } = this;
|
||||
const { ctx, characters } = this;
|
||||
if (characters.length <= 0) return;
|
||||
|
||||
const len = characters.length;
|
||||
const rows = this.headerType === 'minimal' ? 9 : 8;
|
||||
const radius = 80;
|
||||
const fontSize = 72;
|
||||
const radius = 27; // 80/3≈27
|
||||
const fontSize = 24; // 72/3=24
|
||||
|
||||
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;
|
||||
const startY = this.currentY + 10 + radius; // 62/3≈21
|
||||
const startX1 = 103 + radius; // 310/3≈103
|
||||
const startX2 = 67 + radius; // 200/3≈67
|
||||
const spaceWidthFrist = (this.canvasWidth - startX1 * 2) / (5 - 1);
|
||||
const spaceWidthSecond = (this.canvasWidth - startX2 * 2) / (6 - 1);
|
||||
const spaceHeight = 18; // 54/3=18
|
||||
|
||||
ctx.moveTo(startX1, startY);
|
||||
for (let i = 0; i < rows; i++) {
|
||||
@@ -238,7 +183,7 @@ class TextDrawService {
|
||||
|
||||
ctx.fillStyle = '#fff';
|
||||
ctx.strokeStyle = '#000';
|
||||
ctx.lineWidth = 4;
|
||||
ctx.lineWidth = 1; // 4/3≈1
|
||||
ctx.beginPath();
|
||||
ctx.arc(x, y, radius, 0, Math.PI * 2);
|
||||
ctx.fill();
|
||||
@@ -254,36 +199,9 @@ class TextDrawService {
|
||||
}
|
||||
}
|
||||
|
||||
// drawLine 已由基类的 drawDivider 替代,保留此方法以保持兼容
|
||||
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;
|
||||
|
||||
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);
|
||||
this.drawDivider();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user