/** * 图片拼图:模板槽位定义 + Canvas 合成 * 槽位坐标为画布百分比;间距/圆角在绘制时按像素换算。 */ export interface CollageSlot { x: number // % y: number // % w: number // % h: number // % } export interface CollageTemplate { key: string name: string count: number slots: CollageSlot[] } export const COLLAGE_TEMPLATES: CollageTemplate[] = [ { key: 'h2', name: '左右两张', count: 2, slots: [{ x: 0, y: 0, w: 50, h: 100 }, { x: 50, y: 0, w: 50, h: 100 }] }, { key: 'v2', name: '上下两张', count: 2, slots: [{ x: 0, y: 0, w: 100, h: 50 }, { x: 0, y: 50, w: 100, h: 50 }] }, { key: 'l1r2', name: '左大右二', count: 3, slots: [{ x: 0, y: 0, w: 58, h: 100 }, { x: 58, y: 0, w: 42, h: 50 }, { x: 58, y: 50, w: 42, h: 50 }], }, { key: 'h3', name: '三竖条', count: 3, slots: [{ x: 0, y: 0, w: 33.34, h: 100 }, { x: 33.34, y: 0, w: 33.33, h: 100 }, { x: 66.67, y: 0, w: 33.33, h: 100 }] }, { key: 'grid4', name: '四宫格', count: 4, slots: [{ x: 0, y: 0, w: 50, h: 50 }, { x: 50, y: 0, w: 50, h: 50 }, { x: 0, y: 50, w: 50, h: 50 }, { x: 50, y: 50, w: 50, h: 50 }], }, { key: 't1b3', name: '上大下三', count: 4, slots: [{ x: 0, y: 0, w: 100, h: 52 }, { x: 0, y: 52, w: 33.34, h: 48 }, { x: 33.34, y: 52, w: 33.33, h: 48 }, { x: 66.67, y: 52, w: 33.33, h: 48 }], }, ] /** 单槽位圆角矩形 clip + cover 绘制 */ function drawSlot( ctx: CanvasRenderingContext2D, slot: CollageSlot, size: number, img: unknown, imgW: number, imgH: number, gap: number, radius: number, ) { const sx = (slot.x / 100) * size + gap / 2 const sy = (slot.y / 100) * size + gap / 2 const sw = (slot.w / 100) * size - gap const sh = (slot.h / 100) * size - gap if (sw <= 0 || sh <= 0) return const scale = Math.max(sw / imgW, sh / imgH) const dw = imgW * scale const dh = imgH * scale const dx = sx + (sw - dw) / 2 const dy = sy + (sh - dh) / 2 ctx.save() const rr = Math.min(radius, sw / 2, sh / 2) ctx.beginPath() ctx.moveTo(sx + rr, sy) ctx.arcTo(sx + sw, sy, sx + sw, sy + sh, rr) ctx.arcTo(sx + sw, sy + sh, sx, sy + sh, rr) ctx.arcTo(sx, sy + sh, sx, sy, rr) ctx.arcTo(sx, sy, sx + sw, sy, rr) ctx.closePath() ctx.clip() ctx.drawImage(img as CanvasImageSource, dx, dy, dw, dh) ctx.restore() } /** 合成整张拼图 */ export function drawCollage( ctx: CanvasRenderingContext2D, size: number, tpl: CollageTemplate, loaded: Array<{ img: unknown, width: number, height: number }>, gap: number, radius: number, bg: string, ) { ctx.save() ctx.fillStyle = bg ctx.fillRect(0, 0, size, size) ctx.restore() loaded.forEach((item, i) => { const slot = tpl.slots[i] if (slot) drawSlot(ctx, slot, size, item.img, item.width, item.height, gap, radius) }) }