feat: 新增幼儿测字表
This commit is contained in:
@@ -16,6 +16,37 @@ import drawHeader from './drawHeader';
|
||||
const LINE_COLOR = '#BCBAB2'; // 打印友好的深灰线色,避免渐变色
|
||||
const LINE_WIDTH = 3;
|
||||
|
||||
/** 品牌水印模式:A 右下角醒目;B 页面中央大号旋转浅水印(默认) */
|
||||
export type BrandWatermarkMode = 'A' | 'B';
|
||||
|
||||
export interface DrawPrintFooterOptions {
|
||||
/** 默认 B */
|
||||
mode?: BrandWatermarkMode;
|
||||
/** 品牌文案,默认「涂鸦丫小程序」 */
|
||||
text?: string;
|
||||
opacity?: number;
|
||||
fontSize?: number;
|
||||
}
|
||||
|
||||
const BRAND_TEXT = '涂鸦丫小程序';
|
||||
const BRAND_COLOR = '#7C766A';
|
||||
|
||||
/** 方案 A:右下角单行品牌水印 */
|
||||
const FOOTER_MODE_A = {
|
||||
fontSize: 20,
|
||||
opacity: 0.12,
|
||||
marginRight: 24,
|
||||
marginBottom: 20,
|
||||
} as const;
|
||||
|
||||
/** 方案 B:页面中央大号旋转浅水印,单行居中 */
|
||||
const FOOTER_MODE_B = {
|
||||
fontSize: 32,
|
||||
opacity: 0.12,
|
||||
rotationDeg: -25,
|
||||
centerYRatio: 0.52,
|
||||
} as const;
|
||||
|
||||
export class BaseDrawService {
|
||||
canvas: WechatMiniprogram.Canvas;
|
||||
ctx: RenderingContext;
|
||||
@@ -174,24 +205,69 @@ export class BaseDrawService {
|
||||
}
|
||||
|
||||
/**
|
||||
* 页脚:页面底部居中绘制品牌文案「涂鸦丫小程序」(粗体)。
|
||||
* 品牌水印页脚(默认「涂鸦丫小程序」单行)。
|
||||
* - A:右下角水印,适合有底部页码的页面
|
||||
* - B:页面中央大号旋转浅水印(默认)
|
||||
* 请在整页正文绘制完成后调用,避免被内容覆盖。
|
||||
*/
|
||||
async drawPrintFooter(): Promise<void> {
|
||||
drawPrintFooter(options?: DrawPrintFooterOptions): void {
|
||||
const mode = options?.mode ?? 'A';
|
||||
const text = options?.text ?? BRAND_TEXT;
|
||||
|
||||
if (mode === 'A') {
|
||||
this.drawPrintFooterModeA(text, options);
|
||||
} else {
|
||||
this.drawPrintFooterModeB(text, options);
|
||||
}
|
||||
}
|
||||
|
||||
/** 方案 A:右下角单行品牌水印 */
|
||||
private drawPrintFooterModeA(
|
||||
text: string,
|
||||
options?: DrawPrintFooterOptions,
|
||||
): void {
|
||||
const { ctx, canvasWidth, canvasHeight } = this;
|
||||
const text = '涂鸦丫小程序';
|
||||
const bottomMargin = 12;
|
||||
const fontSize = 13;
|
||||
const fontSize = options?.fontSize ?? FOOTER_MODE_A.fontSize;
|
||||
const opacity = options?.opacity ?? FOOTER_MODE_A.opacity;
|
||||
const { marginRight, marginBottom } = FOOTER_MODE_A;
|
||||
const font = `bold ${fontSize}px "Microsoft Yahei", sans-serif`;
|
||||
const textColor = '#7C766A';
|
||||
|
||||
ctx.save();
|
||||
ctx.font = font;
|
||||
ctx.fillStyle = textColor;
|
||||
ctx.fillStyle = BRAND_COLOR;
|
||||
ctx.globalAlpha = opacity;
|
||||
ctx.textAlign = 'right';
|
||||
ctx.textBaseline = 'bottom';
|
||||
ctx.fillText(
|
||||
text,
|
||||
canvasWidth - marginRight,
|
||||
canvasHeight - marginBottom,
|
||||
);
|
||||
ctx.restore();
|
||||
}
|
||||
|
||||
/** 方案 B:页面中央大号旋转浅水印,单行居中 */
|
||||
private drawPrintFooterModeB(
|
||||
text: string,
|
||||
options?: DrawPrintFooterOptions,
|
||||
): void {
|
||||
const { ctx, canvasWidth, canvasHeight } = this;
|
||||
const fontSize = options?.fontSize ?? FOOTER_MODE_B.fontSize;
|
||||
const opacity = options?.opacity ?? FOOTER_MODE_B.opacity;
|
||||
const { rotationDeg, centerYRatio } = FOOTER_MODE_B;
|
||||
const font = `bold ${fontSize}px "Microsoft Yahei", sans-serif`;
|
||||
const centerX = canvasWidth / 2;
|
||||
const centerY = canvasHeight * centerYRatio;
|
||||
|
||||
ctx.save();
|
||||
ctx.font = font;
|
||||
ctx.fillStyle = BRAND_COLOR;
|
||||
ctx.globalAlpha = opacity;
|
||||
ctx.textAlign = 'center';
|
||||
ctx.textBaseline = 'middle';
|
||||
const y = canvasHeight - bottomMargin - fontSize / 2;
|
||||
ctx.fillText(text, canvasWidth / 2, y);
|
||||
ctx.translate(centerX, centerY);
|
||||
ctx.rotate((rotationDeg * Math.PI) / 180);
|
||||
ctx.fillText(text, 0, 0);
|
||||
ctx.restore();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user