微信小程序使用ThreeX开发3d

注意:本代码是用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.这玩意儿很耗模拟器内存,模型体积越小越好,太大可能会加载不出来或者出现贴图丢失,模型渲染出来就是黑色

相关推荐
计算机毕设定制辅导-无忧学长6 小时前
《基于微信小程序健康习惯激励系统设计与实现》
java·spring boot·mysql·微信小程序·uniapp·健康习惯激励系统
拖孩1 天前
流量主门槛从 500 降到 100,我的小程序上线 18 小时够到了线
前端·后端·微信小程序
云-缩影1 天前
做微信小程序,自建服务器还是用云托管:技术选型对比
服务器·微信小程序·小程序
极限挑战哥2 天前
共享电单车联营平台分账架构实践:二清合规与自动分账零人工方案
java·大数据·人工智能·微信小程序·架构·微信公众平台
云-缩影2 天前
拆解微信小程序后端架构:ECS、RDS、SSL 和 VPC 怎么配合
微信小程序·架构·ssl
拖孩2 天前
AI 帮我写的小程序上线 44 天:36 个人进了收银台,8 个人付钱
前端·后端·微信小程序
sinat_267611913 天前
用 AI 开发微信小程序(八):一个极简收纳工具的开发复盘
微信小程序·小程序
码间留白3 天前
鸿蒙也能热更新了:uni-app WGT 热更新的真机结论、六道校验闸与五个深坑
uniapp·ai编程·鸿蒙os开发·鸿蒙热更新·wgt热更新
李纲明3 天前
微信小程序真机预览白屏或 request 失败:先核 request 合法域名与 TLS,再查体验版与本地缓存
缓存·微信小程序·小程序·小程序开发·devdiy·真机预览·合法域名