✨ ThreeJS + VueJS 3 + ViteJS ⚡


ThreeJS + VueJS 3 + ViteJS

NPM Package Build Size NPM Downloads Discord

I wanted to code something similar to react-three-fiber but for VueJS.

I started from scratch, I will rewrite some of my WebGL demos to see if this little toy can do the job.

Trois is a french word, it means Three.

Usage (CDN)

TroisJS is really simple and easy to use :

<div id="app">
  <renderer ref="renderer" antialias orbit-ctrl resize="window">
    <camera :position="{ z: 10 }">camera>
      <point-light :position="{ y: 50, z: 50 }">point-light>
      <box ref="box" :rotation="{ y: Math.PI / 4, z: Math.PI / 4 }">

<script type="module">
  import { createApp } from 'https://unpkg.com/[email protected]/build/trois.module.cdn.min.js';
    mounted() {
      const renderer = this.$refs.renderer;
      const box = this.$refs.box.mesh;
      renderer.onBeforeRender(() => {
        box.rotation.x += 0.01;

Read more on https://troisjs.github.io/guide/


Thanks to VueJS/ViteJS, TroisJS use watchers and HMR to update ThreeJS objects when you update a template or a prop. This means the result in your browser will be automatically updated without reloading all the stuff. This is really helpful when you are creating a TroisJS Scene.


Take a look at examples : https://troisjs.github.io/

  • Lights
    • AmbientLight
    • DirectionalLight
    • HemisphereLight
    • PointLight
    • RectAreaLight
    • SpotLight
  • Materials
    • Basic
    • Lambert
    • Mapcap
    • Phong
    • Physical
    • Shader
    • Standard
    • SubSurface
    • Toon
  • Geometries
    • Box
    • Circle
    • Cone
    • Cylinder
    • Dodecahedron
    • Icosahedron
    • Lathe
    • Octahedron
    • Polyhedron
    • Ring
    • Sphere
    • Tetrahedron
    • Torus
    • TorusKnot
    • Tube
  • Post Processing
    • EffectComposer
      • BokehPass
      • FilmPass
      • FXAAPass
      • HalftonePass
      • Renderpass
      • SMAAPass
      • SSAOPass
      • UnrealBloomPass
      • TiltShiftPass
      • ZoomBlurPass
  • Raycaster does not detect click on GltfModel

    Raycaster does not detect click on GltfModel

    Great library!

    When I use Raycaster it does not detect clicks on loaded Gltf-Models. When I activate the option intersectRecursive and then console log the click event, the intersectObjects list only contains meshes with a direct parent of scene and no loaded models. Is there a hidden attribute that has to be set in the Gltf-Model loading process?

    bug enhancement 
    opened by oneWaveAdrian 12
  • Bundle Size improvements?

    Bundle Size improvements?

    Hi! First thanks for the work and it's great to have some sort of React-Three-Fiber for Vue 🔥

    I was trying it and I'm a bit concerned about the size. With the demo from the README I'm getting a 925kb size. I believe that Trois is importing every component form Three.js, so it makes a very large bundle.

    I was comparing the size and package distributions to React-three-fiber:

    | Bundle size for Trois | Comparassion Bundle Size for React-three-fiber | | --------------- | --------------- | | Screenshot_2021-03-02 BundlePhobia | Screenshot_2021-03-02 BundlePhobia(1) |

    Would it be technically possible to not import Three like React-three-fiber does, or only import the components that are being used by the user?

    Thanks a lot!

    opened by santicros 8
  • Add touch events

    Add touch events

    Raycaster and Object3D interaction methods in #33 need touch events added.

    opened by SaFrMo 7
  • Existing VueJS 3 project

    Existing VueJS 3 project

    Looks like there is some issue with using Trois in projects that already exist. I tried both the import and declare in main process as well as the direct import in the component and I get the same error both ways. I did download the starter app and that worked but I'm more interested in including Trois in my own bundle. I looked up the error in the source and it apparently has something to do with the intersect function. I did try adding Vite and ViteJS plugin-vue to no effect. The error says something about not having a proper loader but I'm not sure that is what the issue is since I tried Vite and it seems the start app is a pretty barebones implementation.

    error  in ./node_modules/troisjs/build/trois.module.js
    Module parse failed: Unexpected token (128:34)
    You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
    |           onIntersectOver(overEvent);
    |           onIntersectEnter(enterEvent);
    >           component.onPointerOver?.(overEvent);
    |           component.onPointerEnter?.(enterEvent);
    |         }
     @ ./node_modules/cache-loader/dist/cjs.js??ref--12-0!./node_modules/babel-loader/lib!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader-v16/dist??ref--0-1!./src/router/views/Home.vue?vue&type=script&lang=js 3:0-84 9:9-12 10:12-18 11:21-36 12:16-26 13:14-22 14:11-16
     @ ./src/router/views/Home.vue?vue&type=script&lang=js
     @ ./src/router/views/Home.vue
     @ ./src/router/index.js
     @ ./src/main.js
     @ multi (webpack)-dev-server/client? (webpack)/hot/dev-server.js ./src/main.js
    bug good first issue 
    opened by Tronological 6
  • added ssao pass

    added ssao pass

    Added SSAO to postprocessing. Example:

      <RenderPass />
      <SSAOPass :options="{ kernelRadius: 0.2, maxDistance: 0.03 }" />

    SSAOPass has quite a few useful options (see here) so the only props in this component are scene (optional), camera (optional), and options. It may be better to leave the options manually to the user by adding lifecycle methods - maybe something like:

    <SSAOPass @ready="prepSSAO"/>
    export default {
      methods: {
          ssao.kernelRadius = 0.2
          ssao.maxRadius = 0.03

    Any thoughts on this @klevron ? Thanks!

    opened by SaFrMo 5
  • Use renderer component to access size, pointer, renderer... ?

    Use renderer component to access size, pointer, renderer... ?

    TroisJS use the following internal helper : https://github.com/troisjs/trois/blob/master/src/core/useThree.js

    It is exposed in components via three injection, but it could be better to hide it and add shortcuts to renderer component to be able to access pointer, threejs renderer, size and ?

    opened by klevron 4
  • add stats option to renderer

    add stats option to renderer

    I ended up needing this for performance testing and thought it'd be useful for others:

      <!-- Add a stats.js FPS monitor, no further config required -->
      <Renderer stats>...</Renderer>
      <!-- Optionally pass a function to handle the created Stats object yourself -->
      <Renderer :stats="onStatsCreated">...</Renderer>
    // only needed if passing a function to `stats`
    export default {
      methods: {
        onStatsCreated(stats) {
          // do something with the Stats object
    Screen shot of three white cubes in a black background with a frames-per-second graph in the top left.

    That also made me think that maybe there should be another onBeforeRender-like callback called onAfterRender - happy to add that in if you'd like @klevron !

    opened by SaFrMo 4
  • InstancedMesh material color not working

    InstancedMesh material color not working

    See here for example. The weird thing is, if I run this locally, it won't work on the first try, but it will if I change the material:


    opened by SaFrMo 4
  • Shader texture proof of concept

    Shader texture proof of concept

    I ran into a situation where I didn't want to prep an entire TextureLoader for a shader texture manually, so I tried this out and it seems to work nicely - it needs a little more polish but I'd love to know your thoughts.

    Basically, instead of providing a texture to a shader in its uniforms:

    <ShaderMaterial :uniforms="uniforms"/>
    // need to import TextureLoader
    // need to declare uniforms
    // need to run this in mounted or other function:
    this.uniforms.texture = { value: new TextureLoader().load('pathToTexture.png') }

    you can use this PR to provide a texture to a shader in the markup, just like a normal TroisJS material:

      <Texture src="pathToTexture.png"/>
    <!-- no JS necessary! -->

    From there, the shader has access to a sampler2D uniform called pathToTexture (the value of the texture's src attribute, minus the extension). You can also specify the uniform name by setting the ID:

      <Texture src="pathToTexture.png" id="myCustomTextureName"/>

    In this case the uniform would be called myCustomTextureName.

    The code in here isn't ready for pull just yet - I'd want to build a more robust regex replacer for the default uniform name, or maybe just throw an error if there isn't an id provided and get rid of the default name functionality entirely. Let me know any thoughts @klevron !

    opened by SaFrMo 4
  • Canvas props

    Canvas props

    Absolutely loving the TS refactor, this is looking excellent @klevron !

    I ran into a situation where I needed an ID and class on the Renderer canvas, so I added support for that (and for arbitrary other canvas attributes) with this PR. Let me know if there are any questions - thanks!

    opened by SaFrMo 4
  • In the context of Vue2, the error Object(...) is reported. Is not a function

    In the context of Vue2, the error Object(...) is reported. Is not a function

    In the VUE2 environment, installed TroisJS and run the result of the reason for the error, I try again under the VUE3 environment, installed TroisJS and run, basically can display. 微信截图_20210720212415

    opened by hjb907310116 0
  • Unable to pause/resume animation (cancelAnimationFrame)

    Unable to pause/resume animation (cancelAnimationFrame)


    Can't seem to find a way to simply pause/resume the request animation frame.

    Looking at the code of trois/src/core/Renderer.ts : , the requestAnimationFrame() function isn't bound/exposed to any variable and therefore i can't pass the raf id the cancelAnimationFrame() function.

    Is there a way to do so that i'm not aware of,?

    Possible solution

    Exposing the local variable raf of Renderer.ts as a synced props?

    Use case:

    I'm rendering an instanciatedMesh of 200k+ cubes, but the scene is static (except when moving the camera) Here is an image of my stress test scene

    opened by vesamet 4
  • Bug: Raycaster does not work on mobile

    Bug: Raycaster does not work on mobile

    When I open my app on a mobile phone, the @click event does not get triggered, when Orbit Controls is active. It seems as if Orbit Controls takes over the input events.

    Example: https://apricot-neighborly-century.glitch.me

    Code: https://glitch.com/edit/#!/apricot-neighborly-century

    Tested on:

    • Android

      • Firefox
      • Chrome
    • MacOS

      • Edge Browser (mobile compatibility Mode)
    opened by oneWaveAdrian 3
  • InstancedMesh use GLTF

    InstancedMesh use GLTF

    Discovered another GLTF oddity, when trying to load a GLTF instead of a standard Geometry, the <InstancedMesh /> will not load correct. Should work according to Three.js example, so I think the


    needs to be updated to reflect that. I know I could do it with raw THREE code, but I think it would make more sense syntax wise if <InstancedMesh /> supports GLTF & FBX

    opened by oneWaveAdrian 3
  • The requested module '/node_modules/.vite/troisjs.497662d1.js' does not provide an export named 'VRButton'

    The requested module '/node_modules/.vite/troisjs.497662d1.js' does not provide an export named 'VRButton'


    Maybe this is something I did wrong but the VRButton doesn't get imported. do I have to import the button or is it imported in the package?

    opened by Slyvan25 2
  • Missing Parent (Scene, Group...)

    Missing Parent (Scene, Group...)

    Hello, thanks for this lib !

    I'm trying to use different component for my app, but got this error (Missing Parent (Scene, Group...)


      <Renderer class="App__canvas" resize="window" :orbit-ctrl="{ enableDamping: true }">
        <Camera :position="{ z: 10 }" />
          <Test />


        <PointLight :position="{ y: 50, z: 50 }" />
          <LambertMaterial color="red" />
    <script setup>
    import { Group, PointLight, Sphere, LambertMaterial } from 'troisjs'

    Don't understand how we can use component inside a Renderer.

    If i use Scene instead of Group in Test.vue it work.. But a scene inside a scene is not a good practice ?

    Thank !

    opened by stephanedemotte 7
  • scene.remove not work

    scene.remove not work

    i'm writing another demo with troisjs recently with three.sprite(not using trois sprite component because the sprite is not supported while coding this demo lol) & scene and i find out that $refs.sceneInstance.remove doesnt work. i've checked the sprites' parent is the scene's reference and $refs.sceneInstance.scene.remove doesn't work as well(but .add() api works fine ,curious) ` //so this part of code do not work // debugger; // activatedNodeInstanceList.forEach(node=>{ // this.$refs.sceneInstance.remove(node); // })

        //directly use removeFromParent api works fine

    ` trois version:0.3.2 three:0.129.0 original src code file besides i see the doc installation is still using ^0.127 which is not support the removeFromParent api , but i check the trois Object3D sourcecode to find out it has already supported removeFromParent api :P

    opened by elineeen 0
  • Use vue-demi for Vue 2

    Use vue-demi for Vue 2

    It would be nice if Vue 3 imports could be replaced with vue-demi. So the plugin also can be use with Vue 2/Nuxt. https://github.com/vueuse/vue-demi

    opened by mahapo 1
  • Possibility to use multiple cameras and scenes

    Possibility to use multiple cameras and scenes

    I need to use both OrthographicCamera and PerspectiveCamera for my projects and is it possible to use this library to create multiple cameras and scenes?

    It seems it's possible to do so with react-three-fiber like this below https://codesandbox.io/s/react-three-fiber-viewcube-py4db?file=/src/App.js

    opened by c-is 2
A D3 Plugin for VueJS

If you are currently using d3vue we are halting updates on this project. We have created a new plugin that more deeply integrates with Vue using a sta

Brian Greig 86 Jun 8, 2021
VueJS module for Flexmonster Pivot Table & Charts

VueJS Module for Flexmonster Pivot Table & Charts

Flexmonster Pivot Table & Charts 12 Jul 26, 2021
A Vue 2 integration using Frappe Charts

Vue 2 Frappe Charts This is a simple package to get using Frappe Charts within VueJS How to use First we need to import and initialize import Vue from

Steve McDougall 144 Jul 13, 2021
📊 Vue.js wrapper for Chart.js

vue-chartjs vue-chartjs is a wrapper for Chart.js in vue. You can easily create reuseable chart components. Demo & Docs ?? Demo ?? Docs Compatibility

Jakub 4.4k Jul 23, 2021
Vue.js(v2.x+) component wrap for ECharts.js(v3.x+)

vue-echarts-v3 Vue.js v2.x+ component wrap for Apache ECharts (incubating) v3.x+ Feature Lightweight, efficient, on-demand binding events; Support for

xLsDg 888 Jul 6, 2021
Easily bind a chart to the data stored in your Vue.js components.

A plugin for adding charts to Vue Table of Contents Purpose Usage Performance Consideration Build Setup Purpose This plugin is designed to allow Vue.j

Brian Greig 193 Jun 25, 2021
A wrapper library for GaugeJS

vgauge A Vue Wrapper to GaugeJS If this package helps you, consider buying me a beer ?? Play Live Demo Installing npm i vgauge --save or <script src="

Amr Essam 40 Mar 11, 2021
Official JSCharting Vue.js Plugin & Examples

JavaScript data visualization for Vue.js JSCharting is a JavaScript data visualization library offering seamless usage with Vue across all devices and

JSCharting 24 Jul 27, 2021
VueJS component wrapping Morris.js

vue-morris Vue.js components wrapping Morris.js lib See http://morrisjs.github.io/morris.js/ for documentation Depends on Vue.js v2.1.0+ Install Use n

Bruno Bonnin 217 Jun 26, 2021
A component of Chartist implement by vuejs 2.0

v-chartist A component of Chartist implements by vuejs 2.0 Installation npm install v-chartist --save or bower install vue-chartist --save Usage imp

LinBin 42 Jun 11, 2021
A Vuejs 2 adapter for Visjs

vue2vis This monorepo hosts Vue2 component wrapper for the visjs libraries. If you are looking for the old [email protected] please use the branch 0.x Usage Pl

null 207 Jul 20, 2021
Create beautiful JavaScript charts with one line of Vue

Vue Chartkick Create beautiful JavaScript charts with one line of Vue See it in action Supports Chart.js, Google Charts, and Highcharts Quick Start Ru

Andrew Kane 691 Jul 24, 2021
⚡️ Vue components based on the JUI chart available in Vue.js

vue-graph A vue component library based on the JUI charts available in vuejs. Installation NPM npm install --save vue-graph Browser Just download dist

JUI Framework 114 May 13, 2021
Vue.js Demos. jQWidgets Vue.js Components - Grids, Charts, Scheduling, Pivot Tables

jQWidgets Vue Components Demos You can view them online here: https://www.jqwidgets.com/vue/. Build modern Web Apps with jQWidgets and Vue. jQWidgets

jQWidgets 52 Jul 6, 2021