// Painter 的 Canvas 2D 实现。Cocos 版本换成 Graphics + Label 即可,HexBoardView 不用改。 import type { Point } from '../src/geom'; import type { Painter } from '../src/painter'; export class CanvasPainter implements Painter { private readonly ctx: CanvasRenderingContext2D; private readonly fontFamily = '"SF Pro Rounded", "PingFang SC", "Helvetica Neue", "Segoe UI", system-ui, -apple-system, sans-serif'; constructor(ctx: CanvasRenderingContext2D) { this.ctx = ctx; } private path(pts: Point[]): void { const ctx = this.ctx; ctx.beginPath(); ctx.moveTo(pts[0].x, pts[0].y); for (let i = 1; i < pts.length; i++) ctx.lineTo(pts[i].x, pts[i].y); ctx.closePath(); } fillPolygon(pts: Point[], color: string, alpha = 1): void { if (alpha <= 0 || pts.length < 3) return; const ctx = this.ctx; ctx.globalAlpha = alpha; ctx.fillStyle = color; this.path(pts); ctx.fill(); ctx.globalAlpha = 1; } strokePolygon(pts: Point[], color: string, lineWidth: number, alpha = 1): void { if (alpha <= 0 || pts.length < 2) return; const ctx = this.ctx; ctx.globalAlpha = alpha; ctx.strokeStyle = color; ctx.lineWidth = lineWidth; ctx.lineJoin = 'round'; this.path(pts); ctx.stroke(); ctx.globalAlpha = 1; } line(x1: number, y1: number, x2: number, y2: number, width: number, color: string, alpha = 1): void { if (alpha <= 0) return; const ctx = this.ctx; ctx.globalAlpha = alpha; ctx.strokeStyle = color; ctx.lineWidth = width; ctx.lineCap = 'round'; ctx.beginPath(); ctx.moveTo(x1, y1); ctx.lineTo(x2, y2); ctx.stroke(); ctx.globalAlpha = 1; } fillCircle(cx: number, cy: number, radius: number, color: string, alpha = 1): void { if (alpha <= 0) return; const ctx = this.ctx; ctx.globalAlpha = alpha; ctx.fillStyle = color; ctx.beginPath(); ctx.arc(cx, cy, radius, 0, Math.PI * 2); ctx.fill(); ctx.globalAlpha = 1; } text(s: string, cx: number, cy: number, size: number, color: string, bold = false, alpha = 1): void { if (alpha <= 0) return; const ctx = this.ctx; ctx.globalAlpha = alpha; ctx.fillStyle = color; ctx.font = `${bold ? '700' : '500'} ${size}px ${this.fontFamily}`; ctx.textAlign = 'center'; ctx.textBaseline = 'middle'; ctx.fillText(s, cx, cy + size * 0.04); ctx.globalAlpha = 1; } }