threejs + vue 倒入ade文件实现动画效果
<template>
<div class="modelsBox">
<div class="modelsBox_wrapper"></div>
<div class="opara-pannel">
<div>
<button @click="save">保存</button>
<button @click="show">回显</button>
</div>
<div>
三维坐标点信息
<p>{{point3d}}</p>
</div>
</div>
</div>
</template>
<script>
import * as THREE from 'three';
// import {AnimationMixer} from 'three';
import { RoomEnvironment } from 'three/examples/jsm/environments/RoomEnvironment.js';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';
import { ColladaLoader } from 'three/examples/jsm/loaders/ColladaLoader.js';
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';
import { KTX2Loader } from 'three/examples/jsm/loaders/KTX2Loader.js';
import { MeshoptDecoder } from 'three/examples/jsm/libs/meshopt_decoder.module.js';
import { webglOBJ, labelTag, getPointRay, getFitScaleValue, deepCopyObject } from '@/utils/webGL/webGL.js';
export default {
name: 'modelsBox',
data () {
return {
point3d: {},
zoom: 1,
target: '',
sence: null,
camera: '',
renderer: '',
obj: {
sence: '',
camera: ''
},
labels: [
{x: 381.0111567102036, y: 41.66598867957452, z: -248.63694417317873},
{x: 383.39332161333544, y: 41.37982005491592, z: -380.9167972387805},
{x: 384.19846417704997, y: 41.50664881726524, z: -466.0620455548741}
]
};
},
beforeDestroy () {
document.removeEventListener('click', this.get3D);
},
mounted () {
this.int();
this.bind3Dpoint();
},
methods: {
// 点击模型获取三维坐标点的信息
bind3Dpoint() {
const vm = this;
document.addEventListener('click', this.get3Dmode, false);
},
get3Dmode () {
console.log(getPointRay(this.sence, this.camera), 'getPointRay');
this.point3d = getPointRay(this.sence, this.camera).point;
},
view (dir) {
if (dir == 'top') {
// this.sence.rotation.x = 10;
this.renderer.render(this.sence, this.camera);
}
},
show () {
const {x, y, z} = JSON.parse(window.sessionStorage.getItem('position'));
this.camera.position.set(x, y, z);
this.camera.lookAt(this.target);
this.renderer.render(this.sence, this.camera);
},
save () {
// this.oCamera = deepCopyObject(this.camera);
const {zoom, position, rotation} = this.camera;
this.target = {...this.controls.target};
window.sessionStorage.setItem('position', JSON.stringify(position));
window.sessionStorage.setItem('target', JSON.stringify(this.target));
},
dele () {
// this.sence.remove(this.plane); // 删除模型
// this.sence.add(this.plane); // 添加模型
console.log(this.camera, this.renderer, 'this.renderer');
},
int () {
const position = window.sessionStorage.getItem('position');
const target = window.sessionStorage.getItem('target');
const webGLdom = document.querySelector('.modelsBox_wrapper');
const sence = webglOBJ.createSence(webGLdom);
const camera = webglOBJ.createCamera({
fov: 45,
aspect: 1,
near: 2,
far: 5000,
position: {
x: 10,
y: 10,
z: 10
}
});
if (position) {
camera.position.set(JSON.parse(position).x, JSON.parse(position).y, JSON.parse(position).z);
camera.lookAt(JSON.parse(target));
}
const renderer = webglOBJ.createRenderer();
const directionalLight = webglOBJ.createDirectionalLight({ x: 100000, y: 100000, z: 100000 }, 1);
const ambient = webglOBJ.createAmbient();
const datGui = webglOBJ.createDatGui();
const controls = webglOBJ.createControls();
const axisHelper = webglOBJ.createAxisHelper();
const grid = new THREE.GridHelper( 500, 10, 0xffffff, 0xffffff );
grid.material.opacity = 0.5;
grid.material.depthWrite = false;
grid.material.transparent = true;
sence.add( grid );
const vm = this;
const loader = new ColladaLoader();
const clock = new THREE.Clock();
loader.load('https://threejs.org/examples/models/collada/stormtrooper/stormtrooper.dae', (collada) => {
const avatar = collada.scene;
console.log(collada, avatar, 'collada.sence');
const animations = collada.animations;
avatar.traverse(function (node) {
if ( node.isSkinnedMesh ) {
node.frustumCulled = false;
}
});
vm.mixer = new THREE.AnimationMixer(avatar);
vm.mixer.clipAction(animations[0]).play();
sence.add(avatar);
});
// 滚动缩小获取比例
controls.addEventListener('change', function(evt) {
// console.log(controls.target, evt, 'zoom');
});
this.sence = sence;
this.controls = controls;
this.camera = camera;
this.renderer = renderer;
// webglOBJ.loadMIT(mtl, obj, (obj) => {
// // console.log(getFitScaleValue(obj, camera), 'adasd');
// });
// 将对象添加到场景中去
webglOBJ.senceAdd([ directionalLight, ambient, datGui, controls, axisHelper]);
// webglOBJ.webglRender(sence, camera, renderer);
function render (html) {
vm.$nextTick(() => {
vm.labels.forEach((val, idx) => {
const {x, y, z} = val;
labelTag(camera, {x, y, z}, `sign${idx + 1}`, val, webGLdom);
});
});
const delta = clock.getDelta();
if (vm.mixer) {
vm.mixer.update(delta);
}
renderer.render(sence, camera);
vm.sence = sence;
vm.camera = camera;
requestAnimationFrame(render);
};
this.render = render;
render();
}
}
};
</script>
<style lang="scss" scoped>
.modelsBox_wrapper {
position: relative;
width: 100%;
height: 100vh;
border: 1px solid #ccc;
overflow: hidden;
}
.opara-pannel {
position: absolute;
right: 15px;
top: 100px;
width: 200px;
height: 400px;
background: rgba(0, 0, 0, 0.7);
div, p{
color: #fff;
}
}
.modelsBox {
position:relative;
overflow: hidden;
}
div[id *= "sign"] {
width: 250px;
height: 100px;
padding:10px 10px 10px 70px;
background: rgba(0, 0, 0, .65);
background: url('~assets/label-bg.png') center center no-repeat;
.sign{
div {
color: #fff;
text-align: left;
padding: 0 5px;
}
}
}
</style>