Files
doodle-mini/miniprogram/mathPages/service/baseMathDraw.ts
T
2025-11-26 18:03:29 +08:00

143 lines
4.3 KiB
TypeScript

import { PAPER_SIZE } from '../../constants/colors';
import { drawMathHeader, drawMathMiniHeader } from './mathHeaderDraw';
/**
* 基础数学绘制服务
* 包含Paper设置和Header绘制功能,可被其他绘制服务复用
*/
export class BaseMathDrawService {
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 || {};
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];
console.log('width', width);
console.log('height', height);
console.log('dpr', dpr);
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 = 24;
this.currentY = 24;
await drawMathHeader({
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() {
drawMathMiniHeader({
ctx: this.ctx,
canvasWidth: this.canvasWidth,
options: {
appName: this.options.appName || '涂鸦丫小程序',
title: this.options.title || '看数字,涂一涂',
},
onHeaderDrawn: (currentY) => {
this.currentY = currentY;
},
});
}
/**
* 绘制分割线(逻辑像素,尺寸除以3)
*/
drawDivider() {
const { ctx, canvasWidth } = this;
const dividerY = this.currentY + 10; // 10px间距
ctx.strokeStyle = '#000';
ctx.lineWidth = 1;
ctx.beginPath();
ctx.moveTo(24, dividerY);
ctx.lineTo(canvasWidth - 24, dividerY);
ctx.stroke();
this.currentY = dividerY + 10; // 分割线下方10px间距
}
}