注意:本代码是用uniapp开发微信小程序,模型使用.glb格式,以下出现(glb模型压缩)代表改代码是使用压缩时需要使用的,不压缩可以不写
Demo:gitee地址 焦明玉/vue2_threex_demo
1.微信小程序后台添加Threex插件
2.manifest.json
javascript
/* 小程序特有相关 */
"mp-weixin": {
"appid": "wx3402c0e00773fc5a",
"setting": {
"urlCheck": false,
"es6": true, // glb模型压缩
"minified": false
},
"usingComponents": true,
"workers": { // glb模型压缩
"path": "workers",
"isSubpackage": true
},
"plugins": {
"ThreeX": {
"version": "3.1.0",
"provider": "wx5d6376b4fc730db9",
"export": "threex.js"
}
}
},
3.threex.js
javascript
module.exports = {
getApp() {
return getApp()
},
getCurrentPages() {
return getCurrentPages()
},
wx_downloadFile() {
return wx.downloadFile
},
wx_request() {
return wx.request
}
}
4.vue.config.js.js (glb模型压缩)
javascript
const path = require('path');
module.exports = {
configureWebpack: {
devServer: {
disableHostCheck: true
},
resolve: {
alias: {
'@workers': path.resolve(__dirname, 'workers')
}
}
},
chainWebpack: config => {
config.module
.rule('js')
.include
.add(path.resolve(__dirname, 'workers'))
.end()
.use('babel-loader')
.loader('babel-loader')
.tap(options => {
// modify the options...
return options;
});
}
};
5.workers目录放置在根目录与pages同级(glb模型压缩)
6.jsm_weixin目录放置在pages下
7.页面使用
javascript
<template>
<view id="page">
<canvas id="canvas_webgl2" type="webgl2" @touchstart="webgl_touch" @touchmove="webgl_touch"
@touchend="webgl_touch" @touchcancel="webgl_touch">
</canvas>
</view>
</template>
<script>
const THREE = requirePlugin("ThreeX")
const {
document,
window,
HTMLCanvasElement,
requestAnimationFrame,
cancelAnimationFrame,
core,
Event,
Event0
} = THREE.DHTML
import {
OrbitControls
} from '../jsm_weixin/controls/OrbitControls.js';
import {
OrbitControls0
} from '../jsm_weixin/controls/OrbitControls0.js';
import {
GLTFLoader
} from '../jsm_weixin/loaders/GLTFLoader.js';
import {
DRACOLoader
} from '../jsm_weixin/loaders/DRACOLoader.js'; // glb模型压缩
let requestId;
export default {
data() {
return {
canvas: {},
renderer: {},
}
},
onUnload() {
cancelAnimationFrame(requestId, this.canvas)
this.worker && this.worker.terminate()
if (this.canvas) this.canvas = null
setTimeout(() => {
if (this.renderer instanceof THREE.WebGLRenderer) {
this.renderer.dispose()
this.renderer.forceContextLoss()
this.renderer.context = null
this.renderer.domElement = null
this.renderer = null
}
}, 10)
},
onLoad() {
uni.showLoading({
title: '模型加载中...',
mask: true
})
document.createElementAsync("canvas", 'webgl2', this).then(canvas => {
this.canvas = canvas
this.run(canvas).then()
})
},
methods: {
// 手指事件
webgl_touch(e) {
const web_e = (window.platform == "devtools" ? Event : Event0).fix(e)
this.canvas.dispatchEvent(web_e)
},
// 初始化渲染模型
async run(canvas) {
// 渲染器
this.renderer = new THREE.WebGLRenderer({
antialias: true,
canvas
});
this.renderer.setPixelRatio(window.devicePixelRatio);
this.renderer.setSize(window.innerWidth, window.innerHeight);
this.renderer.outputEncoding = THREE.sRGBEncoding;
// 场景
let scene = new THREE.Scene();
scene.background = new THREE.Color(0xe7e5e0);
// 相机
let camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 100);
camera.position.set(7, 7, 7);
camera.lookAt(scene.position);
// 控制器
const controls = new(window.platform == "devtools" ? OrbitControls : OrbitControls0)(camera, this
.renderer.domElement);
controls.enablePan = true;
controls.enableZoom = true;
controls.update();
// 坐标系 x轴:红色;Y轴:绿色;Z轴:蓝色
// let axes = new THREE.AxesHelper(5);
// scene.add(axes);
// 环境光
const light0 = new THREE.AmbientLight(0xf7f7dd, 1);
scene.add(light0);
// 平行光
// 平行光源1 头,右
const dLight1 = new THREE.DirectionalLight(0xFFFFFF, 0.5);
dLight1.position.set(5, 0, 10);
scene.add(dLight1);
// 平行光源2 顶,左,后(补充光)
const dLight2 = new THREE.DirectionalLight(0xFFFFFF, 0.5);
dLight2.position.set(-3, 5, 10);
scene.add(dLight2);
// 平行光源3 后,左
const dLight3 = new THREE.DirectionalLight(0xFFFFFF, 0.5);
dLight3.position.set(-5, 0, -10);
scene.add(dLight3);
// 加载模型
// let dracoLoader = new DRACOLoader(); // glb模型压缩
// dracoLoader.setDecoderPath('jsm/libs/draco/gltf/'); // glb模型压缩
let loader = new GLTFLoader();
// loader.setDRACOLoader(dracoLoader); // glb模型压缩
// 压缩:https://zxgj.sxgokit.com:8443/profile/static/3d/3dmodel/3dmodel/DRACO_Car.glb
// 贴图处理:https://zxgj.sxgokit.com:8443/profile/static/3d/3dmodel/3dmodel/car1.glb
loader.load(
'https://zxgj.sxgokit.com:8443/profile/static/3d/3dmodel/3dmodel/car1.glb',
function(gltf) {
gltf.scene.position.set(0, 1.5, -0.5);
gltf.scene.scale.set(1.5, 1.5, 1.5);
scene.add(gltf.scene);
uni.hideLoading()
},
null,
function(e) {
uni.hideLoading();
uni.showToast({
title: '模型加载失败!',
icon: 'none'
})
console.error(e);
}
);
// 动画及渲染
const animate = () => {
requestAnimationFrame(() => {
animate();
});
this.renderer.render(scene, camera);
};
animate();
},
}
}
</script>
<style scoped>
page,
canvas {
overflow: hidden;
width: 100%;
height: 100vh;
background-color: #caeeef;
}
</style>
接下来说一下我遇到的问题:
1.模型加载贴图丢失,贴图太大了最好每张图不超过2kb,1kb最好。使用压缩可以正常显示,但是压缩会引进来约500kbjs代码
2.千万记得模板不要动,不要动,不要动。(模板有问题canvas会报错)下面的js可以修改
3.使用了压缩没有开启es6转es5会报错$gwx啥
4.这玩意儿很耗模拟器内存,模型体积越小越好,太大可能会加载不出来或者出现贴图丢失,模型渲染出来就是黑色