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(); }