uniapp アプレットは 3D モデルを表示します

3D モデルを表示するミニプログラム - レンダリングにthree.jsを使用

開発期間中、膨大な情報や事例を参考にしましたが、そのほとんどがナンセンスでした…検討の末…ついにこのプロジェクトに適した 3D モデルケースを開発しました
。特別に収録させていただきました。

開発期間中に、WeChat でより優れた 3D モデル レンダリングを見つけました。必要な場合は、メッセージを残してください。

効果は図のとおりです (設定後、ここにジェスチャー スライドも追加され、自動回転 3D の種類は obj 形式になります)

ここに画像の説明を挿入します

プロジェクトに必要な依存関係を構成する

安装依赖
npm i

npm i dhtml-weixin
npm i three-weixin

小程序开发工具顶部菜单->工具->构建npm (如果有效果也可以不构建)

html

<template>
	<view class="three_3d">
		<canvas disable-scroll="true" @touchcancel="webgl_touch" @touchend="webgl_touch" @touchmove="webgl_touch"
			@touchstart="webgl_touch" id="canvas_webgl" canvas-id="canvas_webgl" type="webgl"
			style="width:750rpx;height:800rpx;"></canvas>
	</view>
</template>

プロジェクトの依存関係

	import {
    
    
		document,
		window,
		requestAnimationFrame,
		cancelAnimationFrame,
		Event
	} from 'dhtml-weixin';
	import * as THREE from 'three-weixin';
	// import Stats from '../../jsm/libs/stats.module.js';
	// import {
    
    
	// 	GUI
	// } from '../../jsm/libs/lil-gui.module.min.js';
	import {
    
    
		OrbitControls
	} from '../../jsm/controls/OrbitControls.js';
	import {
    
    
		OBJLoader
	} from '../../jsm/loaders/OBJLoader.js';

	var renderer;
	

js

<script>
	export default {
    
    
		name: "threeA",
		data() {
    
    
			return {
    
    
				// renderer: null


			};
		},
		methods: {
    
    
			beforeDestroy() {
    
    
				getApp().worker && getApp().worker.terminate()

				cancelAnimationFrame()
				if (this.renderer) {
    
    
					this.renderer.dispose()
					this.renderer.forceContextLoss()
					this.renderer.context = null
					this.renderer.domElement = null
					this.renderer = null
				}
			},

			webgl_touch(e) {
    
    
				const web_e = Event.fix(e)
				document.dispatchEvent(web_e)
				window.dispatchEvent(web_e)
				this.renderer && this.renderer.dispatchEvent(web_e)
			},
		},
		async onLoad() {
    
    
			getApp().canvas = await document.createElementAsync("canvas", "webgl");
			renderer = new THREE.WebGLRenderer({
    
    
				antialias: true
			});
		},

		async mounted() {
    
    
			// 模型加载需要时间  添加提示 3秒钟后关闭提示正好数据加载出来
			uni.showLoading({
    
    
				title: '加载中',
				duration: 3000
			});

			var that = this;
			getApp().canvas = await document.createElementAsync("canvas", "webgl", this);
			let container;

			let camera, scene, renderer, stats;

			let mouseX = 0,
				mouseY = 0;

			let windowHalfX = window.innerWidth / 2;
			let windowHalfY = window.innerHeight / 2;

			let object;

			init();
			animate();


			function init() {
    
    

				container = document.createElement('div');
				document.body.appendChild(container);

				camera = new THREE.PerspectiveCamera(50, window.innerWidth / window.innerHeight, 1, 2000);
				camera.position.z = 250;

				// scene

				scene = new THREE.Scene();

				const ambientLight = new THREE.AmbientLight(0xcccccc, 0.4);
				scene.add(ambientLight);

				const pointLight = new THREE.PointLight(0xffffff, 0.8);
				camera.add(pointLight);
				scene.add(camera);

				// manager

				function loadModel() {
    
    

					object.traverse(function(child) {
    
    

						//	if ( child.isMesh ) child.material.map = texture;

					});

					object.position.y = -50;
					scene.add(object);

				}

				const manager = new THREE.LoadingManager(loadModel);

				// texture

				const textureLoader = new THREE.TextureLoader(manager);
				//	const texture = textureLoader.load( 'http://localhost:8080/examples/textures/uv_grid_opengl.jpg' );

				// model

				function onProgress(xhr) {
    
    

					if (xhr.lengthComputable) {
    
    

						const percentComplete = xhr.loaded / xhr.total * 100;
						console.log('model ' + Math.round(percentComplete, 2) + '% downloaded');

					}

				}

				function onError() {
    
    }

				const loader = new OBJLoader(manager);
				loader.load('http://youkejingpin.oss-cn-beijing.aliyuncs.com/Digital/static/pic/product/toukui.obj',
					function(obj) {
    
    

						object = obj;

					}, onProgress, onError);

				//原始事件
				// renderer = that.renderer = new THREE.WebGLRenderer();
				// renderer.setPixelRatio(window.devicePixelRatio);
				// renderer.setSize(window.innerWidth, window.innerHeight);
				// container.appendChild(renderer.domElement);

				// document.addEventListener('mousemove', onDocumentMouseMove);
				// window.addEventListener('resize', onWindowResize);
				// 鼠标点击事件
				renderer = that.renderer = new THREE.WebGLRenderer({
    
    
					antialias: true
				});
				renderer.setPixelRatio(window.devicePixelRatio);
				renderer.setSize(window.innerWidth, window.innerHeight);
				renderer.outputEncoding = THREE.sRGBEncoding;
				renderer.shadowMap.enabled = true;
				container.appendChild(renderer.domElement);

				//控制模型触动事件
				camera = new THREE.PerspectiveCamera(55, window.innerWidth / window.innerHeight, 1, 2000);
				camera.position.set(160, 40, 160);

				const controls = new OrbitControls(camera, renderer.domElement);
				controls.enablePan = false;
				controls.enableZoom = true;
				controls.target.set(0, 1, 0);
				controls.update();

				// stats = new Stats();
				// container.appendChild(stats.dom);
				window.addEventListener('resize', onWindowResize);


			}

			function onWindowResize() {
    
    

				windowHalfX = window.innerWidth / 2;
				windowHalfY = window.innerHeight / 2;

				camera.aspect = window.innerWidth / window.innerHeight;
				camera.updateProjectionMatrix();

				renderer.setSize(window.innerWidth, window.innerHeight);

			}

			function onDocumentMouseMove(event) {
    
    

				mouseX = (event.clientX - windowHalfX) / 2;
				mouseY = (event.clientY - windowHalfY) / 2;

			}

			//

			function animate() {
    
    

				requestAnimationFrame(animate);
				render();

			}

			function render() {
    
    

				//camera.position.x += ( mouseX - camera.position.x ) * .05;
				// mera.position.y += ( - mouseY - camera.position.y ) * .05;
				// mera.lookAt( scene.position );
				renderer.render(scene, camera);

				//	console.error(new Date().getTime())
				if (object) {
    
    
					object.rotation.set(0, object.rotation.y + 0.007, 0)
				}


			}

		}
	}
</script>

コード全体を直接使用できます (js+html)

<!-- 模型地址线上地址
http://youkejingpin.oss-cn-beijing.aliyuncs.com/Digital/static/pic/product/toukui.obj
 -->
<template>
	<view class="three_3d">
		<canvas disable-scroll="true" @touchcancel="webgl_touch" @touchend="webgl_touch" @touchmove="webgl_touch"
			@touchstart="webgl_touch" id="canvas_webgl" canvas-id="canvas_webgl" type="webgl"
			style="width:750rpx;height:800rpx;"></canvas>
	</view>
</template>
<script>
	import {
    
    
		document,
		window,
		requestAnimationFrame,
		cancelAnimationFrame,
		Event
	} from 'dhtml-weixin';
	import * as THREE from 'three-weixin';
	import {
    
    
		OrbitControls
	} from '../../jsm/controls/OrbitControls.js';
	import {
    
    
		OBJLoader
	} from '../../jsm/loaders/OBJLoader.js';

	var renderer;
	
	export default {
    
    
		name: "threeA",
		data() {
    
    
			return {
    
    
				// renderer: null


			};
		},
		methods: {
    
    
			beforeDestroy() {
    
    
				getApp().worker && getApp().worker.terminate()

				cancelAnimationFrame()
				if (this.renderer) {
    
    
					this.renderer.dispose()
					this.renderer.forceContextLoss()
					this.renderer.context = null
					this.renderer.domElement = null
					this.renderer = null
				}
			},

			webgl_touch(e) {
    
    
				const web_e = Event.fix(e)
				document.dispatchEvent(web_e)
				window.dispatchEvent(web_e)
				this.renderer && this.renderer.dispatchEvent(web_e)
			},
		},
		async onLoad() {
    
    
			getApp().canvas = await document.createElementAsync("canvas", "webgl");
			renderer = new THREE.WebGLRenderer({
    
    
				antialias: true
			});
		},

		async mounted() {
    
    
			// 模型加载需要时间  添加提示 3秒钟后关闭提示正好数据加载出来
			uni.showLoading({
    
    
				title: '加载中',
				duration: 3000
			});

			var that = this;
			getApp().canvas = await document.createElementAsync("canvas", "webgl", this);
			let container;

			let camera, scene, renderer, stats;

			let mouseX = 0,
				mouseY = 0;

			let windowHalfX = window.innerWidth / 2;
			let windowHalfY = window.innerHeight / 2;

			let object;

			init();
			animate();


			function init() {
    
    

				container = document.createElement('div');
				document.body.appendChild(container);

				camera = new THREE.PerspectiveCamera(50, window.innerWidth / window.innerHeight, 1, 2000);
				camera.position.z = 250;

				// scene

				scene = new THREE.Scene();

				const ambientLight = new THREE.AmbientLight(0xcccccc, 0.4);
				scene.add(ambientLight);

				const pointLight = new THREE.PointLight(0xffffff, 0.8);
				camera.add(pointLight);
				scene.add(camera);

				// manager

				function loadModel() {
    
    

					object.traverse(function(child) {
    
    

						//	if ( child.isMesh ) child.material.map = texture;

					});

					object.position.y = -50;
					scene.add(object);

				}

				const manager = new THREE.LoadingManager(loadModel);

				// texture

				const textureLoader = new THREE.TextureLoader(manager);
				//	const texture = textureLoader.load( 'http://localhost:8080/examples/textures/uv_grid_opengl.jpg' );

				// model

				function onProgress(xhr) {
    
    

					if (xhr.lengthComputable) {
    
    

						const percentComplete = xhr.loaded / xhr.total * 100;
						console.log('model ' + Math.round(percentComplete, 2) + '% downloaded');

					}

				}

				function onError() {
    
    }

				const loader = new OBJLoader(manager);
				loader.load('http://youkejingpin.oss-cn-beijing.aliyuncs.com/Digital/static/pic/product/toukui.obj',
					function(obj) {
    
    

						object = obj;

					}, onProgress, onError);

				//原始事件
				// renderer = that.renderer = new THREE.WebGLRenderer();
				// renderer.setPixelRatio(window.devicePixelRatio);
				// renderer.setSize(window.innerWidth, window.innerHeight);
				// container.appendChild(renderer.domElement);

				// document.addEventListener('mousemove', onDocumentMouseMove);
				// window.addEventListener('resize', onWindowResize);
				// 鼠标点击事件
				renderer = that.renderer = new THREE.WebGLRenderer({
    
    
					antialias: true
				});
				renderer.setPixelRatio(window.devicePixelRatio);
				renderer.setSize(window.innerWidth, window.innerHeight);
				renderer.outputEncoding = THREE.sRGBEncoding;
				renderer.shadowMap.enabled = true;
				container.appendChild(renderer.domElement);

				//控制模型触动事件
				camera = new THREE.PerspectiveCamera(55, window.innerWidth / window.innerHeight, 1, 2000);
				camera.position.set(160, 40, 160);

				const controls = new OrbitControls(camera, renderer.domElement);
				controls.enablePan = false;
				controls.enableZoom = true;
				controls.target.set(0, 1, 0);
				controls.update();

				// stats = new Stats();
				// container.appendChild(stats.dom);
				window.addEventListener('resize', onWindowResize);


			}

			function onWindowResize() {
    
    

				windowHalfX = window.innerWidth / 2;
				windowHalfY = window.innerHeight / 2;

				camera.aspect = window.innerWidth / window.innerHeight;
				camera.updateProjectionMatrix();

				renderer.setSize(window.innerWidth, window.innerHeight);

			}

			function onDocumentMouseMove(event) {
    
    

				mouseX = (event.clientX - windowHalfX) / 2;
				mouseY = (event.clientY - windowHalfY) / 2;

			}
			function animate() {
    
    

				requestAnimationFrame(animate);
				render();

			}

			function render() {
    
    
				//camera.position.x += ( mouseX - camera.position.x ) * .05;
				// mera.position.y += ( - mouseY - camera.position.y ) * .05;
				// mera.lookAt( scene.position );
				renderer.render(scene, camera);

				//	console.error(new Date().getTime())
				if (object) {
    
    
					object.rotation.set(0, object.rotation.y + 0.007, 0)
				}


			}

		}
	}
</script>

<style lang="scss">
	.three_3d {
    
    
		width: 750rpx;
		height: 800rpx;
	}
</style>

プロジェクトの完全なアドレス gitee: https://gitee.com/sun-icon/uniapp3D

おすすめ

転載: blog.csdn.net/sinat_52319736/article/details/126954740
おすすめ