Files
doodle-mini/miniprogram/chinesePages/penControlSheet/shared/penControlDrawUtils.ts
T
2026-05-28 16:46:30 +08:00

104 lines
3.0 KiB
TypeScript

import { TRACING_COLORS } from '../../../core/data/tracingStyles';
import { drawSvgPath } from '../../shared/drawUtils';
import type {
PenControlPattern,
PenControlRenderMode,
} from '../data/penControlPatterns';
export const PEN_CONTROL_VIEW_SIZE = 100;
export interface PenControlTransform {
xOffset: number;
yOffset: number;
scale: number;
}
export function getPenControlTransform(
width: number,
height: number,
padding: number,
): PenControlTransform {
const availableWidth = width - 2 * padding;
const availableHeight = height - 2 * padding;
const scale = Math.min(
availableWidth / PEN_CONTROL_VIEW_SIZE,
availableHeight / PEN_CONTROL_VIEW_SIZE,
);
const scaledW = PEN_CONTROL_VIEW_SIZE * scale;
const scaledH = PEN_CONTROL_VIEW_SIZE * scale;
const xOffset = padding + (availableWidth - scaledW) / 2;
const yOffset = padding + (availableHeight - scaledH) / 2;
return { xOffset, yOffset, scale };
}
export type PenControlCellStyle = 'reference' | 'guide';
function colorForStyle(style: PenControlCellStyle): string {
return style === 'reference' ? TRACING_COLORS.strong : TRACING_COLORS.guide;
}
function drawPathWithMode(
ctx: RenderingContext,
pathD: string,
render: PenControlRenderMode,
color: string,
lineWidth: number,
dashed: boolean,
) {
ctx.beginPath();
drawSvgPath(ctx, pathD);
if (render === 'fill' || render === 'both') {
ctx.fillStyle = color;
ctx.fill();
}
if (render === 'stroke' || render === 'both') {
ctx.strokeStyle = color;
ctx.lineWidth = lineWidth;
if (dashed) {
// setLineDash 接收一个数组,表示虚线的样式。
// 第一个参数 (lineWidth * 2.6):表示每段实线的长度
// 第二个参数 (lineWidth * 2.4):表示每段虚线的间隙长度
// 旧虚线效果不明显,调整为更清晰的虚线样式
ctx.setLineDash([lineWidth * 1.8, lineWidth * 2.3]);
} else {
ctx.setLineDash([]);
}
ctx.stroke();
}
}
/**
* 在田字格中心绘制控笔图形
*/
export function drawPenControlInCell(
ctx: RenderingContext,
pattern: PenControlPattern,
cx: number,
cy: number,
cellSize: number,
style: PenControlCellStyle,
options?: { dashed?: boolean },
) {
const color = colorForStyle(style);
const padding = cellSize * 0.1;
const transform = getPenControlTransform(cellSize, cellSize, padding);
const lineWidth =
(cellSize * 0.0236 * (pattern.strokeScale ?? 1)) / transform.scale;
const dashed = options?.dashed === true;
ctx.save();
ctx.lineCap = 'round';
ctx.lineJoin = 'round';
ctx.translate(cx - cellSize / 2, cy - cellSize / 2);
ctx.translate(transform.xOffset, transform.yOffset);
ctx.scale(transform.scale, transform.scale);
for (const pathD of pattern.paths) {
drawPathWithMode(ctx, pathD, pattern.render, color, lineWidth, dashed);
}
ctx.setLineDash([]);
ctx.restore();
}