150 lines
4.4 KiB
TypeScript
150 lines
4.4 KiB
TypeScript
import { PAPER_SIZE } from '../constants/colors';
|
||
import { drawBaseHeader, drawBaseMiniHeader } from './baseHeaderDraw';
|
||
|
||
/**
|
||
* 基础绘制服务
|
||
* 包含Paper设置和Header绘制功能,可被所有绘制服务复用
|
||
*
|
||
* 提供功能:
|
||
* - Canvas 初始化和配置
|
||
* - Paper 尺寸设置(支持 A4 等标准尺寸)
|
||
* - Header 绘制(支持完整 Header 和迷你 Header)
|
||
* - 分割线绘制
|
||
* - 打印配置管理
|
||
*/
|
||
export class BaseDrawService {
|
||
headerType: PrintHeader = 'wechat';
|
||
canvas: WechatMiniprogram.Canvas;
|
||
ctx: RenderingContext;
|
||
options: Record<string, any>;
|
||
paperSize: PaperSize;
|
||
currentX: number;
|
||
currentY: number;
|
||
canvasWidth: number; // 逻辑像素宽度
|
||
canvasHeight: number; // 逻辑像素高度
|
||
|
||
constructor(
|
||
canvas: Canvas,
|
||
ctx: RenderingContext,
|
||
options?: Record<string, any>,
|
||
) {
|
||
options = options || {};
|
||
const { appName, appHint } = getApp().getPrintConfig();
|
||
this.canvas = canvas;
|
||
this.ctx = ctx;
|
||
this.paperSize = 'A4';
|
||
this.options = {
|
||
appName,
|
||
appHint,
|
||
title: '看数字,涂一涂',
|
||
subTitle: '找一找下面相同的数字,涂上颜色',
|
||
|
||
...options,
|
||
};
|
||
this.currentX = 0;
|
||
this.currentY = 0;
|
||
this.canvasWidth = 0;
|
||
this.canvasHeight = 0;
|
||
this.setPrintConfig();
|
||
}
|
||
|
||
setPrintConfig() {
|
||
const printConfig = getApp().getPrintConfig();
|
||
this.headerType = printConfig.header;
|
||
this.options.appName = printConfig.appName;
|
||
}
|
||
|
||
/**
|
||
* 设置Paper(逻辑像素,尺寸除以3)
|
||
*/
|
||
setPaper() {
|
||
const { ctx, canvas } = this;
|
||
const { pixelRatio: dpr } = wx.getWindowInfo();
|
||
let { width, height } = PAPER_SIZE[this.paperSize];
|
||
|
||
this.canvasWidth = width;
|
||
this.canvasHeight = height;
|
||
|
||
// 设置 canvas 为物理像素尺寸(用于高分辨率显示)
|
||
const physicalWidth = width * dpr;
|
||
const physicalHeight = height * dpr;
|
||
canvas.width = physicalWidth;
|
||
canvas.height = physicalHeight;
|
||
|
||
// 重置 transform 并 scale 到逻辑像素
|
||
ctx.setTransform(1, 0, 0, 1, 0, 0); // 重置 transform
|
||
ctx.scale(dpr, dpr); // scale 到逻辑像素,后续绘制都使用逻辑像素
|
||
|
||
this.clear();
|
||
ctx.fillStyle = '#fff';
|
||
// 使用逻辑像素尺寸填充
|
||
ctx.fillRect(0, 0, this.canvasWidth, this.canvasHeight);
|
||
}
|
||
|
||
/**
|
||
* 清除画布
|
||
*/
|
||
clear() {
|
||
const canvas = this.canvas;
|
||
this.ctx.clearRect(0, 0, canvas.width, canvas.height);
|
||
}
|
||
|
||
/**
|
||
* 绘制Header(逻辑像素,尺寸除以3)
|
||
*/
|
||
async drawHeader() {
|
||
this.currentX = 25;
|
||
this.currentY = 25;
|
||
await drawBaseHeader({
|
||
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;
|
||
},
|
||
});
|
||
}
|
||
|
||
/**
|
||
* 绘制迷你Header(逻辑像素,尺寸除以3)
|
||
*/
|
||
drawMiniHeader() {
|
||
drawBaseMiniHeader({
|
||
ctx: this.ctx,
|
||
canvasWidth: this.canvasWidth,
|
||
options: {
|
||
appName: this.options.appName || '涂鸦丫小程序',
|
||
title: this.options.title || '看数字,涂一涂',
|
||
},
|
||
onHeaderDrawn: (currentY) => {
|
||
console.log('drawMiniHeader currentY', currentY);
|
||
this.currentY = currentY;
|
||
},
|
||
});
|
||
}
|
||
|
||
/**
|
||
* 绘制分割线(逻辑像素,尺寸除以3)
|
||
*/
|
||
drawDivider() {
|
||
const { ctx, canvasWidth } = this;
|
||
const dividerY = this.currentY;
|
||
|
||
ctx.strokeStyle = '#000';
|
||
ctx.lineWidth = 1;
|
||
ctx.beginPath();
|
||
ctx.moveTo(24, dividerY);
|
||
ctx.lineTo(canvasWidth - 24, dividerY);
|
||
ctx.stroke();
|
||
|
||
this.currentY = dividerY + 10; // 分割线下方10px间距
|
||
}
|
||
}
|