700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > vue使用three.js加载.FBX模型文件

vue使用three.js加载.FBX模型文件

时间:2019-09-20 10:49:28

相关推荐

vue使用three.js加载.FBX模型文件

1.需要安装的依赖

//three依赖yarn add three//tween.js依赖yarn add @tweenjs/tween.js

2. 封装组件 draw.vue 放在components中

<template><!-- 三维画布 --><div ref="draw" class="draw" /></template><script>import * as THREE from 'three'; // 三维import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js'; // 控制器export default {name: 'Draw', // 三维画布props: {// // 传入模型函数initLoader: {type: [Function],},// 传入光源数组lightlist: {type: [Array],default: () => {return [{type: 'AmbientLight', // 光的类型color: 0xffffff, // 光的颜色intensity: 1, // 光照强度posiy: [0, 0, 0], // 光照位置},];},},// 传入相机对象sightline: {type: [Object],default: () => {return {scale: 200, // 视线比例type: 'OrthographicCamera', // 相机的类型posiy: [200, 300, 200], // 相机位置};},},// 传入渲染对象strain: {type: [Object],default: () => {return {color: '#FFFFFF', // 背景颜色Encoding: false, // 色彩空间shadow: false, // 渲染阴影};},},// 是否开启鼠标控制orbit: {type: [Boolean],default: true,},},data() {return {scene: null, // 场景对象Scenecamera: null, // 相机对象draw: null, // 节点对象renderer: null, // 渲染器对象controls: null, // 控件对象movetype: -1, // 鼠标事件,默认-1(0点击,1移动isclick: null, // 判断鼠标状态};},mounted() {// 初始化渲染this.init();// 初始化控制this.orbitControls();// 条添加事件this.addmeth();// 设置动画this.tweenUpdate();},methods: {init() {// 初始化场景对象this.initScene();// 初始化模型this.initLoader();// 初始化光源this.initLight();// 初始化相机this.initCamera();// 初始化渲染对象this.initRenderer();// 渲染操作this.animation();},// 初始化场景对象initScene() {// 初始化场景对象this.scene = new THREE.Scene();// 创建三维坐标系var axesHelper = new THREE.AxesHelper(100);// this.scene.add(axesHelper);},// 初始化光源initLight() {// 遍历添加光源this.lightlist.forEach((item) => {var light = new THREE[item.type](item.color, item.intensity);// light.position.set(item.posiy[0], item.posiy[1], item.posiy[2]); // 点光源位置if (item.type === 'DirectionalLight') {light.shadow.camera.near = 20; // 产生阴影的最近距离light.shadow.camera.far = 200; // 产生阴影的最远距离light.shadow.camera.left = -50; // 产生阴影距离位置的最左边位置light.shadow.camera.right = 50; // 最右边light.shadow.camera.top = 50; // 最上边light.shadow.camera.bottom = -50; // 最下面// 这两个值决定使用多少像素生成阴影 默认512light.shadow.mapSize.height = 1024;light.shadow.mapSize.width = 1024;// 告诉平行光需要开启阴影投射light.castShadow = true;}this.scene.add(light);});},// 初始化相机initCamera() {var k = this.$refs.draw.offsetWidth / this.$refs.draw.offsetHeight; // 窗口宽高比// 创建相机对象if (this.sightline.type === 'OrthographicCamera') {this.camera = new THREE.OrthographicCamera(-this.sightline.scale * k,this.sightline.scale * k,this.sightline.scale,-this.sightline.scale,1,1000);} else if (this.sightline.type === 'PerspectiveCamera') {this.camera = new THREE.PerspectiveCamera(this.scale, k, 0.1, 100000);}// 红 绿 蓝this.camera.position.set(this.sightline.posiy[0],this.sightline.posiy[1],this.sightline.posiy[2]); // 设置相机位置this.camera.lookAt(this.scene.position); // 设置相机方向(指向的场景对象)},// 渲染器对象initRenderer() {// 渲染器对象this.renderer = new THREE.WebGLRenderer({ antialias: true });// 设置渲染区域尺寸this.renderer.setSize(this.$refs.draw.offsetWidth,this.$refs.draw.offsetHeight);// three.js 的色彩空间渲染方式 【重要】if (this.strain.Encoding) {this.renderer.outputEncoding = THREE.sRGBEncoding;}if (this.strain.shadow) {// 开启渲染阴影this.renderer.shadowMap.enabled = true;this.renderer.hadowMapEnabled = true;}this.renderer.setClearColor(this.strain.color, 1); // 设置背景颜色// body元素中插入canvas对象this.$refs.draw.appendChild(this.renderer.domElement);},// 执行渲染操作animation() {// 执行渲染操作this.renderer.render(this.scene, this.camera);requestAnimationFrame(this.animation);},// 初始化控制orbitControls() {if (this.orbit) {this.controls = new OrbitControls(this.camera,this.renderer.domElement); // 创建控件对象}},// 添加全局方法addmeth() {// 监听窗口尺寸变化window.addEventListener('resize', this.changeSize, false);// 监听鼠标按下window.addEventListener('mousedown', this.mouseDown, false);// 监听鼠标移动window.addEventListener('mousemove', this.mouseMove, false);// 监听鼠标弹起window.addEventListener('mouseup', this.mouseUp, false);},// 监听尺寸变化changeSize() {// 重置渲染器输出画布canvas尺寸this.renderer.setSize(this.$refs.draw.offsetWidth,this.$refs.draw.offsetHeight);var k = this.$refs.draw.offsetWidth / this.$refs.draw.offsetHeight; // 窗口宽高比// 重置相机投影的相关参数if (this.sightline.type === 'OrthographicCamera') {this.camera.left = -this.sightline.scale * k;this.camera.right = this.sightline.scale * k;this.camera.top = this.sightline.scale;this.camera.bottom = -this.sightline.scale;} else if (this.sightline.type === 'PerspectiveCamera') {camera.aspect = k;}// 如果相机的一些属性发生了变化,// 需要执行updateProjectionMatrix ()方法更新相机的投影矩阵this.camera.updateProjectionMatrix();},// 监听鼠标按下mouseDown(event) {this.isclick = {clientX: event.clientX,clientY: event.clientY,};},// 监听鼠标移动mouseMove(event) {if (!this.isclick) {if (this.$refs.draw) {var list = this.countmouse(event);// 传出鼠标移动事件this.$emit('change', 'move', list);}}},// 监听鼠标弹起mouseUp(event) {// 如果相等说明是点击事件if ((this.isclick.clientX === event.clientX) &(this.isclick.clientY === event.clientY)) {// 传出点击事件this.isclick = null;if (this.$refs.draw) {var list = this.countmouse(event);this.$emit('change', 'click', list);}} else {this.isclick = null;}},// 判断当前点击的事件countmouse(event) {const raycaster = new THREE.Raycaster();const mouse = new THREE.Vector2();// 将鼠标点击位置的屏幕坐标转换成threejs中的标准坐标var dom = this.$refs.draw.getBoundingClientRect();if (event.clientX >= dom.left &&event.clientY >= dom.top &&event.clientX <= dom.left + this.$refs.draw.offsetWidth &&event.clientY <= dom.top + this.$refs.draw.offsetHeight) {mouse.x = (event.clientX / window.innerWidth) * 2 - 1;mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;// 通过鼠标点的位置和当前相机的矩阵计算出raycasterraycaster.setFromCamera(mouse, this.camera);// 获取raycaster直线和所有模型相交的数组集合var list = raycaster.intersectObjects(this.scene.children);if (list.length > 0) {return list;} else {return [];}} else {return [];}},// 设置动画tweenUpdate() {requestAnimationFrame(this.tweenUpdate);this.$tweener.update();},// 运动动画tweenobj(object, potion, time) {this.$tween.fade(object.position,potion,time,0,this.$tweener.Easing.Cubic.InOut);},},};</script><style scoped>.draw {width: 100%;height: 100%;}</style>

3.tween.js 放在utils 文件夹下为了平滑的动画效果

TweenJS:提供了一个简单但强大的渐变界面。它支持渐变的数字对象属性&CSS样式属性,并允许链接补间动画和行动结合起来,创造出复杂的序列。

import TWEEN from '@tweenjs/tween.js'export default {install: function(Vue) {Vue.prototype.$tween = thisVue.prototype.$tweener = TWEEN},pause: function(tw) {tw.pause()},fade: function(target, to, during, delay, easing, onUpdate, onComplete) {if (!target || !to) {return}if (during == null) {during = 260}const tw = new TWEEN.Tween(target).to(to, during)if (delay) tw.delay(delay)tw.easing(easing || TWEEN.Easing.Linear.None)if (onUpdate) tw.onUpdate(onUpdate)if (onComplete) tw.onComplete(onComplete)tw.start()return tw}}

4.在main.js 中配置一下tween

/** 动画 */import tween from './utils/tween'Vue.use(tween)

在页面里正式使用

<template><draw ref="drawWeb" :init-loader="initLoader" />// 有的模型文件较大 几十上百M 显示进度条 提升用户体验<el-progress:text-inside="true":stroke-width="30":percentage="loadedData"/></template><script>import Draw from '@/components/three/draw.vue'export default {components: { Draw },data () {return {loadedData: 0}},methods: {fbxloader (path) {return new Promise(resolve => {var loader = new FBXLoader();loader.load(path, (fbx) => {resolve(fbx)},// 加载过程回调函数onProgress:加载过程不停地重复执行该函数中代码(xhr) => {// 通过加载进度xhr可以控制前端进度条进度 Math.floor:小数加载进度取整this.loadedData = Math.floor(xhr.loaded / xhr.total * 100)})});},initLoader () {this.fbxloader(this.showImgDia).then((tree) => {//加载模型this.$refs.drawWeb.scene.add(tree);});},fbxTrue (src) {//此为判断文件是否为fbx结尾,有需要自取 不是必要方法let str = falseif (src.toLowerCase().substr(-3, 3) == 'fbx') {str = true}return str},}}</script>

大功告成,吃饭大吉!

ps: 曾以为走不出的日子,现在都回不去了。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。