diff --git a/frontend/src/components/KiraAvatar.tsx b/frontend/src/components/KiraAvatar.tsx index 90bf3a4..c931919 100644 --- a/frontend/src/components/KiraAvatar.tsx +++ b/frontend/src/components/KiraAvatar.tsx @@ -24,7 +24,6 @@ const OUTFIT_TEXTURES: Record = { export default function KiraAvatar(props: Props) { const canvasRef = useRef(null); - const appRef = useRef(null); const modelRef = useRef(null); const textureRef = useRef(null); const lipSyncRef = useRef(0); @@ -41,6 +40,16 @@ export default function KiraAvatar(props: Props) { let app: any = null; let model: any = null; + let canvasEl: HTMLCanvasElement | null = null; + + const fitModel = (crW: number, crH: number) => { + if (!model || !app) return; + const maxW = crW * 0.65; + const maxH = crH * 0.65; + const s = Math.min(maxW / model.width, maxH / model.height); + model.scale.set(s); + model.position.set(app.screen.width / 2, app.screen.height / 2); + }; const init = async () => { try { @@ -73,6 +82,7 @@ export default function KiraAvatar(props: Props) { canvas.style.height = '100%'; canvas.style.display = 'block'; container.appendChild(canvas); + canvasEl = canvas; model = await Live2DModel.from('/live2d/models/kira/kira.model3.json', { autoInteract: false, @@ -80,8 +90,8 @@ export default function KiraAvatar(props: Props) { modelRef.current = model; // Fit model with generous margin to avoid clipping - const maxW = w * 0.68; - const maxH = h * 0.68; + const maxW = w * 0.65; + const maxH = h * 0.65; const scale = Math.min(maxW / model.width, maxH / model.height); model.scale.set(scale); model.anchor.set(0.5, 0.5); @@ -117,17 +127,16 @@ export default function KiraAvatar(props: Props) { // Use ResizeObserver so we init with the real laid-out size const ro = new ResizeObserver((entries) => { + const cr = entries[0].contentRect; if (app) { // Already init'd — handle resize - const cr = entries[0].contentRect; app.renderer.resize(Math.round(cr.width), Math.round(cr.height)); - if (model) { - const maxW = cr.width * 0.68; - const maxH = cr.height * 0.68; - const s = Math.min(maxW / model.width, maxH / model.height); - model.scale.set(s); - model.position.set(app.screen.width / 2, app.screen.height / 2); + // Re-apply CSS 100% because Pixi resize() overwrites inline styles + if (canvasEl) { + canvasEl.style.width = '100%'; + canvasEl.style.height = '100%'; } + fitModel(cr.width, cr.height); return; } // First measurement — run init