view-3d-model

1.3.2 • Public • Published

view-3d-model

NPM Package NPM Downloads

view-3d-model is a Vue.js library that makes use of three.js and GLTFLoader to allow users to display 3D models in their Vue.js applications.

This can be achieved by importing the ThreeDModel component from the library, which supports models in gltf format, as well as the binary version of gltf, which is glb.

npm install view-3d-model
<script setup>
  import ThreeDModel from "view-3d-model";
</script>

<template>
  <div class="wrapper">
    <ThreeDModel
      class="three-d-model"
      file-path="./models/your-model-name.glb"
      :use-editor="true"
      :custom-settings="{
      autoRotate: true
    }"
    />
  </div>
</template>

<style>
  .wrapper {
    height: 100vh;
    width: 100vw;
  }

  .three-d-model {
    height: 100%;
    width: 100%;
  }
</style>

Chapters

This documentation includes the following chapters:

Get Started
Using ThreeDModel
Customize `ThreeDModel` with props
Control `ThreeDModel` with CSS
Extensions
Troubleshooting
Create a Vue.js Project
ThreeDModel

Get Started

Prerequisites

To use view-3d-model you will need a Vue.js project (or a Nuxt project), and a gltf(glb) file.

  • If you are unfamiliar to the Vue.js javascript framework, see this guide to create a Vue.js project

  • If you don't have a gltf(glb) file, there are plenty of free downloads on the web. For example you can visit Sketchfab, and download a 3d-model of your liking. Make sure that you choose the file format gltf or glb.

ℹ️ The glb version usually is about 30% smaller than the gltf version and thus recommended to use if possible.

Start using view-3d-model

When you have a glb or gltf file, and a Vue.js project (or a Nuxt project), follow these steps to start using view-3d-model:

Create a folder for your models

  • Lets create a folder called models inside the public folder.

ℹ️ If you are using Nuxt use the static folder instead of public.

Using glb

  • If you have a model of the format glb, you can simply add the file to the models folder as it is:
your-project/
...
    public/                              // Use static folder if using Nuxt
        models/
            name-of-your-model.glb
...

Using gltf

  • If you have a model of the format gltf, you'll notice that it consists of a number of different items. Usually there is a texture folder or a number of image files, a bin file, a license.txt file and a gltf file. Create a folder with the name of your model inside the models folder, and add all the contents of the gltf file to this folder.

Your project should look something like this:

your-project/
...
    public/                             // Use static folder if using Nuxt
        models/
            name-of-your-model/
                textures
                license.txt
                scene.bin
                scene.gltf

...

Install view-3d-model

  • Install view-3d-model by typing the following in the command line:
npm install view-3d-model

Import and use the ThreeDModel component in Vue.js projects

Click here to see how to import and use ThreeDModel in Nuxt project

Follow these steps to import and use the ThreeDModel component in your Vue.js project:

In App.vue, or any other component where you want to use ThreeDModel:

Using Composition API (Vue 3):

<script setup>
  // import the ThreeDModel component from view-3d-model
  import ThreeDModel from "view-3d-model";
</script>

<template>
  <div class="wrapper">
    <!-- If using glb format -->
    <ThreeDModel
      class="three-d-model"
      file-path="./models/your-model-name.glb"
    />

    <!-- If using gltf format -->
    <ThreeDModel
      class="three-d-model"
      file-path="./models/your-model-name/scene.gltf"
    />
  </div>
</template>
<!-- In this example we set the width and height to match the viewport. -->
<style>
  .wrapper {
    height: 100vh;
    width: 100vw;
  }

  .three-d-model {
    height: 100%;
    width: 100%;
  }
</style>

Using Options API (Vue 2):

<template>
  <div class="wrapper">
    <!-- If using glb format -->
    <ThreeDModel
      class="three-d-model"
      file-path="./models/your-model-name.glb"
    />

    <!-- If using gltf format -->
    <ThreeDModel
      class="three-d-model"
      file-path="./models/your-model-name/scene.gltf"
    />
  </div>
</template>

<script>
  // import the ThreeDModel component from view-3d-model
  import ThreeDModel from "view-3d-model";
  export default {
    name: "nameOfYourComponent",
    // Declare ThreeDModel in component options
    components: {
      ThreeDModel,
    },
  };
</script>
<!-- In this example we set the width and height to match the viewport. -->
<style>
  .wrapper {
    height: 100vh;
    width: 100vw;
  }

  .three-d-model {
    height: 100%;
    width: 100%;
  }
</style>

To make ThreeDModel available globally throughout your Vue.js project add this to main.js:

import { createApp } from "vue";
import App from "./App.vue";
// Import ThreeDModel from view-3d-model
import ThreeDModel from "view-3d-model";

createApp(App)
  // Register ThreeDModel as global component
  .component("ThreeDModel", ThreeDModel)
  .mount("#app");

Now you can use ThreeDModel wherever you want in your Vue.js project without importing it in your components. Click here to see how to start using ThreeDModel

Import and use the ThreeDModel component in Nuxt.js projects

  • If you haven't already done so, install view-3d-model by typing the following in the command line:
npm install view-3d-model
  • In the plugins folder create a file called view-3d-model.js.

  • Copy and paste the following into plugins/view-3d-model.js:

import Vue from "vue";
import ThreeDModel from "view-3d-model";

Vue.component("ThreeDModel", {
  extends: ThreeDModel,
});
  • In nuxt.config.js, add the following to the plugins array:
...
    plugins: [
        ...
            {src: '~/plugins/view-3d-model.js', mode: 'client'}
        ...
    ]
...
  • Also in nuxt.config.js, add view-3d-model to build.transpile:
...
  build: {
    ...
      transpile: ['view-3d-model']
    ...
  }
...

Now ThreeDModel is available globally throughout your Nuxt project without importing it in your components like so:

<template>
    <!-- If using glb format -->
    <client-only>
      <div class="wrapper">
        <ThreeDModel
          class="three-d-model"
          file-path="./models/your-model-name.glb"
        />
      </div>
    </client-only>

    <!-- If using gltf format -->
    <client-only>
      <div class="wrapper">
        <ThreeDModel
          class="three-d-model"
          file-path="./models/your-model-name/scene.gltf"
        />
    </client-only>

</template>

<script>
  export default {
    name: "nameOfYourComponent",
  };
</script>
<!-- In this example we set the width and height to match the viewport. -->
<style>
  .wrapper {
    height: 100vh;
    width: 100vw;
  }

  .three-d-model {
    height: 100%;
    width: 100%;
  }
</style>

Using ThreeDModel

By now you should have a 3d model rendered to the screen. Now let's take a look at how you can adjust the settings of the model via props.

Short on props in Vue.js

  • ThreeDModel takes three props: filePath, useEditor and customSettings. When we're passing props to a Vue component we typically do so in kebab-case, so in this guide we will be following that convention. (As in the examples above when we're passing the filePath prop, we do so like this: file-path="./models/your-model-name.glb").

  • When we want to send a dynamic prop value, a javascript expression or a number rather than a string, we will use the : v-bind shortcut like so:

<ThreeDModel
  class="three-d-model"
  file-path="./models/your-model-name.glb"
  :use-editor="true"
/>

Here we're passing the prop useEditor using v-bind which means the value will be the Boolean value true. Without the : the value would be a String value 'true'.

Customize ThreeDModel with props

ThreeDModel takes three props:

  • filePath (String)

    We've already used the required prop filePath which is the path that points at your 3d-model to be loaded.
  • customSettings (Object):

    An object that specifies settings to camera, lighting, orbit controls and rotation. The default values looks like this:
{
//  Field of view, defines the extent of the scene that is seen on the display. Set in degrees, defaults to 50.
//  type: Number, min: 1, max: 180
   fov: 50,

 // Camera position, will be used if x, y and z is provided. Else it will be ignored and the camera position will be set automatically.
//  type: Number,  min: -50, max: 50
   cameraPosition: {
     x: null,
     y: null,
     z: null,
   },

  // Exposure level, defaults to 1
  // type: Number, min: 0, max: 10
  exposure: 1,

 // A light in a specific direction, used to simulate daylight
 // Position is set to x:0, y:1, z:0 meaning that the light shines from the top down.
 // Set intensity and color adjust the light
   directionalLight: {
    // type: Number, min: 0, max: 100
     intensity: 0.5,
    // Recommended: Hex("FFFFFF") or Dec(16777215)
     color: "#FFFFFF",
   },

 // Illuminates the scene equally, without direction, set intensity and color to adjust the light
   ambientLight: {
    // type: Number, min: 0, max: 100
     intensity: 0.1,
    //Recommended: Hex("#FFFFFF") or Dec(16777215)
     color: "#FFFFFF",
   },

 // If set to true enables to interact with the model (zoom, grab, rotate), defaults to true
 // type: Boolean
 enableOrbitControls: true,

 // If set to true rotates the model, defaults to false
 // Type: Boolean
 autoRotate: false,

 // The rotation speed if autoRotate is set to true, defaults to 2
 // type: Number, min: 0.1, max: 100
 rotationSpeed: 2,

}

You can pass the customSettings prop to adjust all or some of the values like in this example:

ℹ️ Note that when passing values to the cameraPosition all of the properties x, y and z are required. If one or two of these values are left out, ThreeDModel will fall back to its default behaviour and set the camera position automatically

<ThreeDModel
  class="three-d-model"
  file-path="./models/your-model-name.glb"
  :use-editor="true"
  :custom-settings="{
    fov: 70,
    directionalLight: {
      intensity: 1
    },
    autoRotate: true
  }"
/>

Here we increase the fov value to 70, raises the intensity of the directionalLight to 1, and sets the autoRotate to true.

To make it easier to set the values of the customSettings prop, it's recommended to use the editor by setting prop useEditor to true.

:information_sourse: Note that if the model you are using was created using the extension KHR_materials_unlit, no lights will be applicable, and thus no controls for directionalLight and ambientLight will show up in the editor. read more about extensions here

  • useEditor (Boolean)

    When we set the value of prop useEditor to true, an editor will be created. This editor lets you play around and adjust the settings of the camera, the lighting, orbit controls and rotation.

If you want to use the current settings there are two options:

ℹ️ Note that the prop 'useEditor' will not be included when using Copy as Template or Use Settings

  • Click the Copy as Template button, which will copy a ThreeDModel template to the clipboard that you can paste into your project.
  • Click the Use Settings button. This will $emit an event with the current settings wich makes it possible to listen to the event in your parent component like so:

Using composition API (Vue 3):

<script setup>
  ...
    function handleSettings(settings) {
      console.log('current settings: ', settings)
    }
  ...
</script>

<template>
  ...
  <ThreeDModel
    class="three-d-model"
    file-path="./models/your-model-name.glb"
    :use-editor="true"
    @use-settings="data => handleSettings(data)"
  />
  ...
</template>

Using Options API (Vue 2):

<template>
  ...
  <ThreeDModel
    class="three-d-model"
    file-path="./models/your-model-name.glb"
    :use-editor="true"
    @use-settings="data => handleSettings(data)"
  />
  ...
</template>

<script>
  export default {
    ...
      methods: {
        handleSettings(settings) {
          console.log('current settings: ', settings)
        }
      }
  ...
  };
</script>

The function handleSettings will be called everytime you click the useSettings button in the editor. If you want save the settings in a database or similar, just put your logic for this in the handleSettings function.

Control ThreeDModel with CSS

Here you can read about how to use CSS to control the 3d model

Set width and height

  • In order to work correctly the ThreeDmodel component needs a width and height. If not, the width and height properties of the rendered canvas element that holds your model will be 0 and thus your model won't be visible. It's recommended to wrap the ThreeDModel in a div, and set the width and height of ThreeDModel relative to the wrapper div:
<template>
  <div class="wrapper">
    <ThreeDModel
      class="three-d-model"
      file-path="./models/your-model-name.glb"
    />
  </div>
</template>

<!-- In this example we set the width and height to match the viewport. -->
<style>
  .wrapper {
    height: 100vh;
    width: 100vw;
  }

  .three-d-model {
    height: 100%;
    width: 100%;
  }
</style>

We can use the CSS property aspect-ratio to define the ratio between width and height of the wrapper:

<template>
  <div class="wrapper">
    <ThreeDModel
      class="three-d-model"
      file-path="./models/your-model-name.glb"
    />
  </div>
</template>
<!-- In this example we set the width of the wrapper to 80vw and the aspect-ratio to 4/3. -->
<style>
  .wrapper {
    width: 80vw;
    aspect-ratio: 4/3;
  }

  .three-d-model {
    height: 100%;
    width: 100%;
  }
</style>

If we want we can use media querys to set the size of the wrapper:

<template>
  <div class="wrapper">
    <ThreeDModel
      class="three-d-model"
      file-path="./models/your-model-name.glb"
    />
  </div>
</template>
<!-- In this example we use a media query breakpoint to change the width on larger devices -->
<style>
  .wrapper {
    width: 100vw;
    aspect-ratio: 4 / 3;
  }

  @media screen and (min-width: 992px) {
    .wrapper {
      width: 50vw;
    }
  }

  .three-d-model {
    height: 100%;
    width: 100%;
  }
</style>

By default ThreeDModel will center the model and set the the camera position. Here you can read about how to adjust the camera position and other settings.

Set background

To set the background color you simply do so by setting it either to the ThreeDModel itself or it's parent like so:

<template>
  <div class="wrapper">
    <ThreeDModel
      class="three-d-model"
      file-path="./models/your-model-name.glb"
    />
  </div>
</template>
<style>
  .wrapper {
    background-color: #29bdc1;
    width: 80vw;
    aspect-ratio: 4/3;
  }

  .three-d-model {
    height: 100%;
    width: 100%;
  }
</style>

Or you can use a background image like in this example:

<template>
  <div class="wrapper">
    <ThreeDModel
      class="three-d-model"
      file-path="./models/your-model-name.glb"
    />
  </div>
</template>

<style>
  .wrapper {
    width: 100vw;
    height: 100vh;
    background-image: url("https://images.pexels.com/photos/1242348/pexels-photo-1242348.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1");
    background-repeat: no-repeat;
    background-position: center;
    background-size: cover;
  }

  .three-d-model {
    width: 100%;
    height: 100%;
  }
</style>

Extensions

When creating a gltf file there are a number of extensions one can use. view-3d-model is using three.js to load and render 3d models, and thus supports the same extensions as the GLTFLoader in the three.js library.

While the most common extensions out there are supported, sometimes trying to load a file with a an unknown extensions can lead to problems.

One example of this worth mentioning is the deprecated extension KHR_materials_pbrSpecularGlossiness). Support for this extensions in three.js was dropped in november 2022, and while most gltfs already use the workflow metal/rough instead there still are some downloads using the extension. To solve this you'll need to convert the file to metal/rough. If your model is using this extension you will get a console message with a link to this article where you can read about how to convert spec/gloss to metal/rough.

Another common case which is not a problem but worth mentioning to avoid confusion, is when the gltf was created using the extension KHR_materials_unlit. When so, no lights will be applicable to the model and hence no controls for ambientLight or directionalLight will be created in the editor. read more about the KHR_materials_unlit extension here.

Supported extensions:

  • KHR_draco_mesh_compression
  • KHR_materials_clearcoat
  • KHR_materials_ior
  • KHR_materials_specular
  • KHR_materials_transmission
  • KHR_materials_iridescence
  • KHR_materials_unlit
  • KHR_materials_volume
  • KHR_mesh_quantization
  • KHR_lights_punctual1
  • KHR_texture_basisu
  • KHR_texture_transform
  • EXT_texture_webp
  • EXT_meshopt_compression
  • EXT_mesh_gpu_instancing

Supported by an external user plugin:

  • KHR_materials_variants2
  • MSFT_texture_dds

To read more about supported extensions in three.js GLTFLoader, click here

Troubleshooting

Common issues and solutions

My 3d model doesn't show up

  • Make sure your provided filePath is correct. If you're using gltf file format, your path shuld point at the gltf file. Also make sure that all the gltf resources such as textures etc is located in the same folder as the gltf file. If the file is not found you will get a message in the console.

  • Make sure that the ThreeDModel has a width and height. Since the ThreeDModel adapts to the width and height given to it, it might not be visible if not having these values. Read more about how to control ThreeDModel with CSS here

ℹ️ Note that if you're setting height and width using relative lenght %, the parent element must have a height and width

I can't set the lights

  • This probably means that the 3d model was created using the extension KHR_materials_unlit. This means no lights are applicable to the model and hence no controls are created for ambientLight or directionalLight in the editor. Read more about extensions here

My model is not looking correct

Create a Vue.js Project

ℹ️ Since Vue 2 support will end on Dec 31 2023, this guide will show you how to create a Vue 3 project

ℹ️ For detailed explanation on how things work, checkout Vue.js official documentation

Follow these steps to create a Vue.js application:

  • Open up an empty project in your code editor.
  • Make sure that you have Node.js version 16.0 or higher installed:
    • If you havent alreday, you can download Node.js here, choose the LTS(long-term-support) version.
    • You can check your Node.js version by typing the following in the command line:

node --version

  • When you've made sure that your version is 16.0 or above, type the following in the command line:

npm init vue@latest

This command will install and execute create-vue, which is the official Vue project scaffolding tool.

You will be presented with prompts for several optional features. For now let's choose No on all options (you only need to fill in the Project name) and you should see something like this:


Project name: <your-project-name>
✔ Project name: … <your-project-name>
✔ Add TypeScript? … No / Yes
✔ Add JSX Support? … No / Yes
✔ Add Vue Router for Single Page Application development? … No / Yes
✔ Add Pinia for state management? … No / Yes
✔ Add Vitest for Unit testing? … No / Yes
✔ Add Cypress for both Unit and End-to-End testing? … No / Yes
✔ Add ESLint for code quality? … No / Yes
✔ Add Prettier for code formatting? … No / Yes

Scaffolding project in ./<your-project-name>...
Done.

  • Once your project is created you run the following in the command line:

cd <your-project-name>


npm install


npm run dev

Now you should have your Vue project running on http://localhost:5173/.

If you want to change the port you can do so in the package.json file like so:

{
  "name": "your-project-name",
  "version": "0.0.0",
  "private": true,
  "scripts": {
    "dev": "vite --port 3000", // Here you can change to your preferred port
    "build": "vite build",
    "preview": "vite preview"
  },
  "dependencies": {
    "vue": "^3.2.47"
  },
  "devDependencies": {
    "@vitejs/plugin-vue": "^4.0.0",
    "vite": "^4.1.4"
  }
}

Open the App.vue file inside the src folder it will look something like this:

<script setup>
  import HelloWorld from "./components/HelloWorld.vue";
  import TheWelcome from "./components/TheWelcome.vue";
</script>

<template>
  <header>
    <img
      alt="Vue logo"
      class="logo"
      src="./assets/logo.svg"
      width="125"
      height="125"
    />

    <div class="wrapper">
      <HelloWorld msg="You did it!" />
    </div>
  </header>

  <main>
    <TheWelcome />
  </main>
</template>

<style scoped>
  header {
    line-height: 1.5;
  }
  .logo {
    display: block;
    margin: 0 auto 2rem;
  }
  @media (min-width: 1024px) {
    header {
      display: flex;
      place-items: center;
      padding-right: calc(var(--section-gap) / 2);
    }
    .logo {
      margin: 0 2rem 0 0;
    }
    header .wrapper {
      display: flex;
      place-items: flex-start;
      flex-wrap: wrap;
    }
  }
</style>

As you can see there are some autogenerated files in the components folder.

These files are imported in the App.vue and used to create a welcome page.

  • Let's remove the files in the components folder.
  • Clean up the App.vue file so that it looks like this:
<script setup></script>

<template> </template>

<style scoped></style>

In the assets folder there are two auto generated css files: main.css and base.css. These files are used to set a base styling to the application. You can remove or change the css in these files if you want to.

Now you can continue here to get started with view-3d-model in your project.

ThreeDModel

Props

Name Description Type Required Default
filePath Path to model String true -
useEditor If set to true, an editor will be created to help adjust settings Boolean false false
customSettings An object with settings to control camera, lighting, orbit controls and rotation Object false {fov: 50, cameraPosition: {x: null,y: null,z: null}, exposure: 1, directionalLight: {intensity: 0.5, color: "#FFFFFF"}, ambientLight: {intensity: 0.1,color: "#FFFFFF"}, enableOrbitControls: true, autoRotate: false, rotationSpeed: 2}

Events

Event Name Description Parameters
useSettings Fire when 'Use settings' button is clicked The argument is an object with the current settings

Methods

Method Description Parameters
initialize Creating scene, camera and renderer -
setLights Adding lights to the scene Using values from props 'ambientLighting' and 'directionalLigthing' -
animate Adding animation loop -
setEnvironment Adding an environment to the scene, to provide an even lighting to the scene -
createLoader Creating gltfLoader Creating dracoLoader which is used if gltf is compressed with draco -
checkExtensions Setting isUnlit to true if method/usingUnllit returns true. Logs a warning if method/usingSpecGloss returns true extensions, extensionsUsed
usingUnlit Returns true or false depending on if extension 'KHR_materials_unlit' is used. extensions, extensionsused
usingSpecGloss Returns true or false depending on if extension 'KHR_materials_pbrSpecularGlossiness' is used. extensions, extensionsused
getCenterAndSize Creating a bounding box from model and returns the size and center -
centerModel Centering the loaded model -
setCamera Setting the camera position size, center
setControls Adding orbit controls to be able to interact with the model, enabled if enableOrbitControls is set to true size
setRotation Adding rotation if autoRotate is set to true and rotation speed -
updateCamera Updating camera projectionMatrix -
render Renders the scene and camera -
updateCameraAndRenderer Updating camera aspect ratio, projectionMatrix and renderers size -
onWindowResize Runs updateCameraAndRenderer on window resize window -
getCurrentSettings Returns the current settings att any given moment. Will be used when emitting or copying settings from editor. -
handleUseSettings Emitting current settings -
handleCopy Copies a ThreeDModel template with current settings to clipboard -
triggerCopyMsg Setting 'showCopyMsg' to true for one second -
resetEditor Resets all values in Editor -
createEditor Creating GUI to help adjusting the model -

Readme

Keywords

Package Sidebar

Install

npm i view-3d-model

Weekly Downloads

1

Version

1.3.2

License

ISC

Unpacked Size

64.3 kB

Total Files

15

Last publish

Collaborators

  • patriknyfeldt