import {useId} from 'react'; import selections from '../content/templates/selection.json'; export type SourceLayout=typeof selections[number]; export type CoverValues={fields:Record;color:string;accent:string}; export {selections}; export function SourceCover({layout,values,guides=false}:{layout:SourceLayout;values:CoverValues;guides?:boolean}){ const uid=useId().replace(/:/g,''),W=layout.width*10,H=layout.height*10; return {layout.name+' · 封面试版'}文字为可编辑占位,图位和装饰按原图构件重建为矢量,原始分层数据保留在模板 JSON 中。来源 {layout.tutorialUrl} {['image','decoration','text'].flatMap(kind=>layout.slots.filter(s=>s.kind===kind).map(s=>{ const [x,y,w,h]=s.box.map(n=>n*10); if(kind==='image')return {layout.id==='ref-07'?:}; if(kind==='decoration'){ if(layout.id==='ref-07')return {[550,595,640,685,730,775,820].map(r=>)}; if(layout.id==='ref-26'&&s.id==='D04')return ; return ; } const text=values.fields[s.id]||'',lines=text.split('\n').slice(0,4),length=(str:string)=>Array.from(str).reduce((sum,c)=>sum+(/[\u3400-\u9fff]/.test(c)?1:.6),0),size=Math.min(h/(lines.length*1.25),w/Math.max(1,...lines.map(length))*.94); if(s.direction==='vertical'){const letters=Array.from(text.replace(/\n/g,'')),font=Math.min(w*.88,h/Math.max(1,letters.length));return {letters.map((c,i)=>{c})}} if(s.direction==='curved'){ const letters=Array.from(text),font=Math.min(36,w/Math.max(1,letters.length*.9)); return {letters.map((letter,i)=>{const t=.08+.84*(i+.5)/letters.length,px=x+w*t,py=y+3.9*h*t*(1-t),angle=Math.atan(3.9*h*(1-2*t)/w)*180/Math.PI;return {letter}})}; } return 100?"Georgia,'PingFang SC',serif":"Arial,'PingFang SC',sans-serif"}>{lines.map((line,i)=>{line})}; }))} {guides&&} ; }