实现效果
Tips:先泼个冷水,这个预览3D组件有个致命的缺陷——不能设置材质、皮肤文件的目录路径,必须要和3d文件放在同一个目录,如果项目是用hash模式(url后面会有/#/这种井号),就会导致无法读取根目录的材质文件。所以推荐了解下 vue-3d-loader
安装先
npm install vue-3d-model --save
属性
prop | type | default | example |
src | string | - | './exapmle.obj' |
width | number | - | 300 |
height | number | - | 300 |
position | object | { x: 0, y: 0, z: 0 } | { x: 100, y: 20, z: -10 } |
rotation | object | { x: 0, y: 0, z: 0 } | { x: Math.PI / 2, y: 0, z: - Math.PI / 4 } |
cameraPosition | object | { x: 0, y: 0, z: 0 } | { x: 1, y: 2, z: -3 } |
cameraRotation | object | { x: 0, y: 0, z: 0 } | { x: 3, y: 2, z: -1 } |
scale | object | { x: 1, y: 1, z: 1 } | { x: 2, y: 2, z: 3 } |
lights | array | - | |
backgroundColor | number/string | 0xffffff | 0xffffff/'#f00'/'rgb(255,255,255)' |
backgroundAlpha | number | 1 | 0.5 |
controlsOptions | object | - | see OrbitControls Propertiesopen in new window |
crossOrigin | string | anonymous | anonymous/use-credentials |
requestHeader | object | - | { 'Authorization: Bearer token' } |
outputEncoding | number | THREE.LinearEncoding | see WebGLRenderer OutputEncodingopen in new window |
glOptions | object | { antialias: true, alpha: true } | see WebGLRenderer Parametersopen in new window |
事件
event |
mousedown |
mousemove |
mouseup |
click |
load |
progress |
error |
插槽
slots |
progress-bar |
poster |
<template> <div class="threeDPreview"> <!-- 3D立体文件预览 --> <div if="threeDComponents" class="threeD"> <component :is="threeDComponents.componentName" :backgroundAlpha="1" :backgroundColor="'#000'" :rotation="ratation" :src="`${encodeURIComponent(_fileURL)}`" @load="onLoad" /> </div> </div> </template> <script> //引入3D预览插件 npm install vue-3d-model --save import { ModelCollada, ModelFbx, ModelGltf, ModelThree, ModelObj, ModelPly, ModelStl, } from 'vue-3d-model'; export default { components: { ModelCollada, ModelFbx, ModelGltf, ModelThree, ModelObj, ModelPly, ModelStl, }, data() { return { load: null, threeDfileTypes: [ { label: 'dae', value: 1, iconURL: 'static/img/fileType/3D/dae.svg', componentName: 'ModelCollada' }, { label: 'fbx', value: 2, iconURL: 'static/img/fileType/3D/fbx.svg', componentName: 'ModelFbx' }, { label: 'gltf', value: 3, iconURL: 'static/img/fileType/3D/gltf.svg', componentName: 'ModelGltf' }, { label: 'json', value: 4, iconURL: 'static/img/fileType/3D/json.svg', componentName: 'ModelThree' }, { label: 'obj', value: 5, iconURL: 'static/img/fileType/3D/obj.svg', componentName: 'ModelObj' }, { label: 'ply', value: 6, iconURL: 'static/img/fileType/3D/ply.svg', componentName: 'ModelPly' }, { label: 'stl', value: 7, iconURL: 'static/img/fileType/3D/stl.svg', componentName: 'ModelStl' }, ], ratation: { x: -Math.PI / 2, y: 0, z: 0, }, _fileURL: '', _fileType: '', }; }, props: ["fileURL", "fileType"], watch: { fileURL: { handler(d) { this._fileURL = decodeURIComponent(d || this.$route.query.fileURL); }, deep: true, immediate: true, }, fileType: { handler(d) { this._fileType = d || this._fileURL.split('.').slice(-1)[0]; // 如果是3D文件个后缀名格式 if (this.threeDfileTypes.find(v => v.label == this._fileType)) { this.showLoad(); } }, deep: true, immediate: true, }, }, computed: { threeDComponents() { return this.threeDfileTypes.find(v => v.label == this._fileType); }, }, methods: { showLoad() { this.load = this.$loading({ text: "加载中…" }); }, hideLoad() { this.load && this.load.close(); }, onLoad(d) { this.rotate(); this.hideLoad(); }, rotate() { requestAnimationFrame(this.rotate);//实现自动旋转效果 this.rotation.z += 0.01; }, } }; </script> <style lang="scss" scoped> .threeDPreview { position: relative; .threeD { width: 100%; height: calc(100vh - 60px); } } </style>
相关API文档来源:
可能会遇到的报错
其他可以预览3D的组件,前列腺推荐!