DocumentationJavaScript

JavaScript

React에 의존하지 않는 기본 API를 사용합니다.

생성·로드·정리

JavaScript API는 Canvas 하나를 관리합니다. 모델을 조작하기 전에 로드가 끝날 때까지 기다리고, 화면에서 제거할 때는 반드시 dispose()를 호출하세요.

ts
import { createLive2D } from 'live2d-web'
 
const character = await createLive2D({
  container: document.querySelector('#avatar'),
  coreUrl: '/live2dcubismcore.min.js',
  src: '/models/model.model3.json',
})
 
await character.motion('TapBody', 0)
 
// When the host view is removed:
character.dispose()

모델을 여럿 올리기

addModel()은 같은 캔버스에 모델을 하나 더 올립니다. 두 번째 캐릭터가 두 번째 WebGL 컨텍스트가 아니라 모델 하나로 끝납니다. 브라우저는 컨텍스트 개수에 상한이 있습니다.

two.ts
const stage = await createLive2D({
  container: document.querySelector('#stage')!,
  coreUrl: '/live2dcubismcore.min.js',
  src: '/models/host.model3.json',
})
 
const guest = await stage.addModel({
  src: '/models/guest.model3.json',
  fit: { scale: 0.8, offsetX: 0.3, units: 'stage' },
})
 
await guest.motion('Tap', 0)
guest.dispose()

추가한 순서대로 그려지므로 나중에 올린 모델이 위에 옵니다. 모델마다 자기 fit, 모션, 표정, 파라미터, 히트 영역을 갖고, 하나를 지워도 캔버스와 나머지는 그대로 있습니다. src는 선택입니다. 빼면 빈 캔버스로 시작해 addModel()로 채웁니다.

인스턴스의 motion()이나 fit 같은 메서드는 그대로 남아 src로 만든 모델을 가리킵니다. 배치 오버레이는 한 번에 한 모델만 갖습니다.

Canvas 접근성

Canvas를 보조 기술에 노출해야 할 때만 의미를 지정하세요. 옵션을 생략하면 기존 마크업을 그대로 유지합니다.

ts
const character = await createLive2D({
  accessibility: {
    label: '움직이는 안내 캐릭터',
    fallbackText: '안내 캐릭터 그림',
  },
  container: document.querySelector('#avatar'),
  src: '/models/model.model3.json',
})

정보를 전달하지 않는 모델에는 { mode: 'decorative' }를 사용하세요. 탭과 모션 동작은 키보드로 조작할 수 있는 일반 DOM 버튼이나 컨트롤로도 제공해야 합니다. 런타임은 Canvas에 tabIndex나 role="application"을 자동 추가하지 않습니다.

화면 생명주기와 맞추기

인스턴스는 컨테이너를 소유한 화면에서 보관하세요. 숨겨진 탭에서 애니메이션이 필요 없다면 일시 정지하고, 화면이 사라질 때 정리합니다. dispose()는 여러 번 호출해도 안전합니다.

ts
const onVisibility = () => document.hidden ? character.pause() : character.resume()
document.addEventListener('visibilitychange', onVisibility)
 
window.addEventListener('pagehide', () => {
  document.removeEventListener('visibilitychange', onVisibility)
  character.dispose()
}, { once: true })

Vue, Svelte, 그 밖의 프레임워크

전용 진입점은 React에만 있습니다. 컴포넌트 트리는 생명주기 훅에는 없는 도움이 필요하기 때문입니다. React는 Strict Mode에서 effect를 두 번 실행하고, 동시에 렌더링하며, 정리 시점을 스스로 정합니다. 다른 프레임워크에서는 명령형 API가 곧 바인딩입니다. 컴포넌트가 마운트될 때 인스턴스를 만들고, 사라질 때 정리하고, 그 사이에는 프레임워크가 부르는 이름의 지역 상태에 담아 두면 됩니다.

Vue
<script setup lang="ts">
import { createLive2D } from 'live2d-web'
import { onBeforeUnmount, onMounted, ref } from 'vue'
 
const host = ref<HTMLElement>()
let character: Awaited<ReturnType<typeof createLive2D>> | undefined
 
onMounted(async () => {
  character = await createLive2D({
    container: host.value!,
    coreUrl: '/live2dcubismcore.min.js',
    src: '/models/model.model3.json',
  })
})
 
onBeforeUnmount(() => character?.dispose())
</script>
 
<template>
  <div ref="host" />
</template>

Vue Vite 예제에 전체가 있습니다. Svelte, Solid, Angular도 생명주기 이름만 다를 뿐 형태는 같습니다.

조작과 재시도 UI 만들기

모션, 표정, 재시도는 Canvas 밖의 일반 버튼으로 제공하세요. 로드 전에는 비활성화하고, 실패하면 Live2DError.code를 표시합니다. Core 경로, 모델 자산, WebGL 환경을 수정한 뒤 새 인스턴스로 재시도하세요.