TroisJS: Three.js for Vue 3
TroisJS is a powerful and lightweight library designed to facilitate the creation of 3D graphics and animations within Vue 3 applications, leveraging the capabilities of Three.js and the performance benefits of Vite. Currently stable at version 0.3.4, the library maintains a relatively active release cadence, frequently pushing bug fixes and minor features as seen in recent patch versions (e.g., 0.3.4, 0.3.2). Its primary differentiator is providing a `react-three-fiber`-like component-based API specifically tailored for the Vue ecosystem, allowing developers to compose complex Three.js scenes declaratively using Vue components. It ships with comprehensive TypeScript types, ensuring robust development and better maintainability for large-scale projects. The library aims to abstract away much of the boilerplate associated with direct Three.js integration into a Vue environment, making 3D development more accessible to Vue developers.
Common errors
-
Error: Cannot find module 'troisjs'
cause The `troisjs` package has not been installed or correctly linked in your project.fixRun `npm install troisjs three vue` or `yarn add troisjs three vue` to install the package and its core peer dependencies. -
[Vue warn]: Failed to resolve component: <component-name>
cause TroisJS components (e.g., <Renderer>, <Box>) are not globally registered or locally imported in your Vue application.fixEnsure you have called `app.use(TroisJSVuePlugin)` during your Vue application initialization, or explicitly import and register the component locally within your Vue SFCs if not using the plugin. -
TypeError: Cannot read properties of null (reading 'scene')
cause Attempting to access properties of a TroisJS component's underlying Three.js object (e.g., `renderer.scene`) before the component has fully mounted and initialized.fixUse Vue's lifecycle hooks like `onMounted` or `nextTick` to ensure the component is rendered and its internal Three.js objects are available before attempting to interact with them programmatically. Use `ref` and optional chaining (`?.`) for safer access.
Warnings
- breaking Version 0.3.0 introduced TypeScript support. While not explicitly listed as a breaking change in the changelog for this specific transition, users migrating from pre-0.3.0 JavaScript versions to 0.3.0+ TypeScript projects might encounter type-related issues or require adjustments to their codebase to conform to new type definitions and stricter API contracts.
- gotcha Event handling for pointer interactions (e.g., click, hover) on 3D objects sometimes fails to register correctly, particularly with complex GLTF models or specific camera setups.
- gotcha When using `ShaderMaterial` with custom textures, issues might arise where the texture is not correctly applied or rendered.
Install
-
npm install troisjs -
yarn add troisjs -
pnpm add troisjs
Imports
- TroisJSVuePlugin
import TroisJSVuePlugin from 'troisjs'
import { TroisJSVuePlugin } from 'troisjs' - Renderer
import Renderer from 'troisjs'
import { Renderer } from 'troisjs' - useRenderer
import { useRenderer } from 'troisjs'
Quickstart
import { createApp } from 'vue'
import { TroisJSVuePlugin } from 'troisjs'
import { ref, onMounted } from 'vue'
const app = createApp({
template: `
<renderer ref="rendererRef" antialias orbit-ctrl resize="window">
<camera :position="{ z: 10 }"></camera>
<scene>
<point-light :position="{ y: 50, z: 50 }"></point-light>
<box ref="boxRef" :rotation="{ y: rotation.y, z: rotation.z }">
<lambert-material></lambert-material>
</box>
</scene>
</renderer>
`,
setup() {
const rendererRef = ref(null)
const boxRef = ref(null)
const rotation = ref({ y: Math.PI / 4, z: Math.PI / 4 })
onMounted(() => {
// Access the Three.js scene, camera, etc. via rendererRef.value.scene, etc.
if (rendererRef.value && boxRef.value) {
console.log('Renderer and Box components mounted.')
// Example: animate box rotation
rendererRef.value.onBeforeRender(() => {
rotation.value.y += 0.01
rotation.value.z += 0.005
})
}
})
return { rendererRef, boxRef, rotation }
}
})
app.use(TroisJSVuePlugin).mount('#app')