Components

Since Lunchbox is a Vue 3 custom renderer, it can support any Three.js class.

Out of the box, it supports the classes listed in the autoGeneratedComponents array in the source code. To add more classes, see Extend.

Properties

Lunchbox can also support any Three.js property on any component. Vue props and directives (ref, v-for, v-if, key, etc) are not passed onto Lunchbox-created instances.

Lunchbox will do its best to use the correct type for the prop:

:scale="[2, 2, 2]"      // Vector3s that receive arrays will spread array values into <vector3>.set
:scale="2"              // Vector3s that receive numbers will be set via <vector3>.setScalar
:color="'blue'"         // colors will be set using `<color>.set`

You can also set nested props by replacing dots with dashes:

:position-x="2" // equivalent to <item>.position.x = 2
:scale-y="3"    // equivalent to <item>.scale.y = 3
:exampleEntry-z="5" // equivalent to <item>.exampleEntry.z

Lunchbox reserves the following props for internal use:

  • args - used when creating an instance of a Three.js class. args must be an array; its values will be spread into the instantiation method.
<!-- a sphere with radius=15, widthSegments=32, heightSegments=16 -->
<sphereGeometry :args="[15, 32, 16]"></sphereGeometry>

One-time use args

Each Lunchbox component is only created once in its lifecycle, so args will only apply on instantiation:

<template>
    <Lunchbox>
        <mesh>
            <sphereGeometry :args="[radius]" />
        </mesh>
    </Lunchbox>
</template>

<script>
    export default {
        data() {
            return { radius: 5 }
        },
        mounted() {
            // This will have no effect on the sphere - since the radius is 5 at instantiation,
            // the value 20 will not be used again.
            setTimeout(() => (this.radius = 20), 1000)

            // If you need a new sphere with the new radius, add the prop `:key="radius"`
            // to the mesh to reinstantiate the entire component on radius change:
            //
            // <mesh :key="radius">
            //  <sphereGeometry :args="[radius]"/>
            // </mesh>
            //
            // or edit the scale of the mesh for the same effect:
            //
            // <mesh :scale="radius === 5 ? 1 : 4">
        },
    }
</script>

Methods

You can also call methods declaratively in components:

<webGLRenderer :setSize="[256, 256]" />

(See here for the setSize method and here for more information on extra renderers.)

The main caveat is that you need to wrap all arguments in an array, just like with the args prop:

<!-- works -->
<example :methodCall="[256]" />

<!-- doesn't work -->
<example :methodCall="256" />

Setting functions

There is one exception to this rule: some functions (like onAfterRender and onBeforeRender) are set rather than called directly:

const mesh = new THREE.Mesh()
// onBeforeRender is called internally by Three.js
// and is set by the user like this:
mesh.onBeforeRender = () => {
    /* ... */
}

Use single values for these rather than arrays:

<!-- works -->
<mesh :onBeforeRender="myCustomMethod" />

<!-- doesn't work -->
<mesh :onBeforeRender="[myCustomMethod]" />

Events

All Lunchbox components emit an onAdded (or @added) and onReady (or @ready) event:

<mesh @added="yourAddedMethod" @ready="yourReadyMethod" />

onAdded fires when the instance has been added to its scene or parent. onReady fires when the instance has first been created - it may or may not exist in the scene yet. Both accept an object with the following properties:

{
        instance, // the instantiated Three.js object
}

Additional events available to Lunchbox components are:

@ Naming

Note you can replace on with @ in the event names below. onClick is the same as @click, etc.

NameParameters
onAdded{ instance: <instantiated type> }
onClick{ intersection: THREE.Intersection }
onClick{ intersection: THREE.Intersection }
onPointerUp{ intersection: THREE.Intersection }
onPointerDown{ intersection: THREE.Intersection }
onPointerOver{ intersection: THREE.Intersection }
onPointerOut{ intersection: THREE.Intersection }
onPointerEnter{ intersection: THREE.Intersection }
onPointerLeave{ intersection: THREE.Intersection }
onPointerMove{ intersection: THREE.Intersection }
onReady{ instance: <instantiated type> }