view-3d-model v1.3.2
view-3d-model
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
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.jsjavascript framework, see this guide to create a Vue.js projectIf 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 formatgltforglb.
:information_source: 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
modelsinside thepublicfolder.
:information_source: 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 themodelsfolder 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 atexture folderor a number of image files, abinfile, alicense.txtfile and agltffile. Create a folder with the name of your model inside themodelsfolder, and add all the contents of thegltffile 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-modelIn the
pluginsfolder create a file calledview-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 thepluginsarray:
...
plugins: [
...
{src: '~/plugins/view-3d-model.js', mode: 'client'}
...
]
...- Also in
nuxt.config.js, add view-3d-model tobuild.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
ThreeDModeltakes three props:filePath,useEditorandcustomSettings. When we're passing props to a Vue component we typically do so inkebab-case, so in this guide we will be following that convention. (As in the examples above when we're passing thefilePathprop, 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-bindshortcut 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:
We've already used the required propfilePath (String)filePathwhich is the path that points at your 3d-model to be loaded.
An object that specifies settings to camera, lighting, orbit controls and rotation. The default values looks like this:customSettings (Object):
{
// 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:
:information_source: 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
When we set the value of propuseEditor(Boolean)useEditortotrue, 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:
:information_source: Note that the prop 'useEditor' will not be included when using Copy as Template or Use Settings
- Click the
Copy as Templatebutton, which will copy aThreeDModeltemplate to the clipboard that you can paste into your project. - Click the
Use Settingsbutton. This will$emitan 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
ThreeDmodelcomponent 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 theThreeDModelin a div, and set the width and height ofThreeDModelrelative 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
filePathis correct. If you're usinggltffile format, your path shuld point at the gltf file. Also make sure that all thegltfresources such as textures etc is located in the same folder as thegltffile. If the file is not found you will get a message in the console.Make sure that the
ThreeDModelhas a width and height. Since theThreeDModeladapts to the width and height given to it, it might not be visible if not having these values. Read more about how to controlThreeDModelwith CSS here
:information_source: 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 forambientLightordirectionalLightin the editor. Read more about extensions here
My model is not looking correct
- This could be due to the
gltfwas created using an unsupported extension. Check the console for messages. Read more about extensions here
Create a Vue.js Project
:information_source: Since Vue 2 support will end on Dec 31 2023, this guide will show you how to create a Vue 3 project
:information_source: 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.jsversion 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.jsversion by typing the following in the command line:
- If you havent alreday, you can download Node.js here, choose the
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@latestThis 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 installnpm run devNow 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.vuefile 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 | - |
2 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago