UNPKG

next-live2d

Version:

A simple React component to embed Live2D models (via `live2d-widget`) in Next.js projects.

67 lines (66 loc) 2.46 kB
'use client'; import { useEffect } from 'react'; export default function Live2DWidget({ modelName, style, className }) { const modelJsonPath = `https://raw.githubusercontent.com/dangtranhuu/next-live2d/refs/heads/main/models/${modelName}/model.json`; useEffect(() => { // ✅ Đã khởi tạo rồi thì không lặp lại if (window.__live2d_initialized) return; const script = document.createElement('script'); script.src = 'https://cdn.jsdelivr.net/npm/live2d-widget@3.1.4/lib/L2Dwidget.min.js'; script.async = true; script.onload = () => { if (window.__live2d_initialized) return; // @ts-ignore window.L2Dwidget?.init({ model: { jsonPath: modelJsonPath, }, display: { position: 'right', width: 180, height: 300, }, mobile: { show: true, }, react: { opacityDefault: 0.8, opacityOnHover: 0.2, }, }); window.__live2d_initialized = true; const waitForWidget = () => { const el = document.querySelector('#live2d-widget'); if (!el) return requestAnimationFrame(waitForWidget); Object.assign(el.style, { position: 'fixed', right: '0px', transition: 'bottom 0.3s ease-in-out', zIndex: '9999', pointerEvents: 'none', ...style, }); if (className) { el.className += ' ' + className; } }; waitForWidget(); }; document.body.appendChild(script); return () => { // ✅ cleanup an toàn tuyệt đối const widget = document.querySelector('#live2d-widget'); if (widget?.parentNode) { widget.parentNode.removeChild(widget); } // ✅ xóa flag để có thể re-init lần sau nếu cần window.L2Dwidget = undefined; window.__live2d_initialized = false; }; }, [modelJsonPath, style, className]); return null; }