原创

uniapp 使用three-platformize 引入绘画正方体和交互

温馨提示:
本文最后更新于 2024年04月03日,已超过 96 天没有更新。若文章内的图片失效(无法正常加载),请留言反馈或直接联系我
<template>
	<view>
		<canvas canvas-id="myCanvas" disable-scroll id="myCanvas" type="webgl" style="width: 100vw; height: 100vh;" @tap="onCanvasTap" @touchstart="onTX" @touchmove="onTX"
			@touchend="onTX"></canvas>
		<view style="position: absolute; top: 20px; left: 20px;z-index: 12;">
			<button @tap="zoomIn" v-if="!isNarrow">放大</button>
			<button @tap="zoomIn1" v-if="isNarrow">缩小</button>
		</view>
	</view>
</template>
<script>
	import * as THREE from 'three-platformize';
	import {
		WechatPlatform
	} from 'three-platformize/src/WechatPlatform'
	import {
		OrbitControls
	} from 'three-platformize/examples/jsm/controls/OrbitControls'
	let raycaster = new THREE.Raycaster();
	let mouse = new THREE.Vector2();
	let selectedSpheres = [];
	export default {
		data() {
			return {
				spheres: [],
				lines: [],
				camera: null,
				scene: null,
				isNarrow:false,
				scaleFactor:1
			};
		},
		onReady: function() {

			uni.createSelectorQuery().select('#myCanvas').node().exec((res) => {
				const canvas = res[0].node

				this.platform = new WechatPlatform(canvas)
				THREE.PLATFORM.set(this.platform);

				const scene = new THREE.Scene();

				this.scene = scene
				const camera = new THREE.PerspectiveCamera(75, canvas.width / canvas.height, 0.1, 1000);
				this.camera = camera
				const renderer = new THREE.WebGL1Renderer({
					canvas,
					antialias: true,
					alpha: true
				})
				this.renderer = renderer
				// 添加背景图
				const loader = new THREE.TextureLoader();
				const backgroundTexture = loader.load('/static/2.jpeg');
				// scene.background = new THREE.Color(0x000000); // 设置背景颜色
				scene.background = backgroundTexture;
				// 添加星星背景特效
			// 	const particles = new THREE.Group();
			// 	const particleCount = 1000;
			
			// 	const particleTexture = new THREE.TextureLoader().load('/static/1.jpg');
			// 	const particleMaterial = new THREE.PointsMaterial({ color: 0xffffff, size: 20, map: particleTexture, transparent: true });
			
			// 	for (let i = 0; i < particleCount; i++) {
			// 		const x = (Math.random() - 0.5) * 2000;
			// 		const y = (Math.random() - 0.5) * 2000;
			// 		const z = (Math.random() - 0.5) * 2000;
			
			// 		const particle = new THREE.Vector3(x, y, z);
			// 		const geometry = new THREE.BufferGeometry().setFromPoints([particle]);
			// 		particles.add(new THREE.Points(geometry, particleMaterial));
			// 	}
			
			// 	scene.add(particles);

				
				// 添加平行光
				const light = new THREE.DirectionalLight(0xffffff);
				light.position.set(1, 1, 1).normalize();
				scene.add(light);
				
				// 创建透明的正方体
				const cubeGeometry = new THREE.BoxBufferGeometry(4, 4, 4);
				const cubeMaterial = new THREE.MeshLambertMaterial({ color: 0xFFFFFF, transparent: true, opacity: 0.5 });
				const cube = new THREE.Mesh(cubeGeometry, cubeMaterial);
				scene.add(cube);
				
				// 创建四周的线条
				var edges = new THREE.EdgesGeometry(cubeGeometry);
				var edgesMaterial = new THREE.LineBasicMaterial({
					color: 0x1890ff,
					linewidth: 1,
				})
				var line = new THREE.LineSegments(edges, edgesMaterial);
				scene.add(cube, line);
					
				 // 创建第一个球形
				const geometry1 = new THREE.SphereGeometry(0.2, 32, 32);
				const material1 = new THREE.MeshLambertMaterial({ color: 0xff0000 });
				const sphere1 = new THREE.Mesh(geometry1, material1);
				sphere1.position.set(-0.8, -0.8, 0);
				scene.add(sphere1);
			
				// 创建第二个球形
				const geometry2 = new THREE.SphereGeometry(0.2, 32, 32);
				const material2 = new THREE.MeshLambertMaterial({ color: 0x00ff00 });
				const sphere2 = new THREE.Mesh(geometry2, material2);
				sphere2.position.set(0, 0, 0);
				scene.add(sphere2);
			
				// 创建第三个球形
				const geometry3 = new THREE.SphereGeometry(0.2, 32, 32);
				const material3 = new THREE.MeshLambertMaterial({ color: 0x0000ff });
				const sphere3 = new THREE.Mesh(geometry3, material3);
				sphere3.position.set(0.8, 0.8, 0);
				scene.add(sphere3);
				
				this.spheres = [sphere1,sphere2,sphere3]

				camera.position.z = 10;

				const controls = new OrbitControls(camera, renderer.domElement);
				// controls.autoRotate = false //设置自动旋转
				// controls.dampingFactor = 0.25; // 动态阻尼系数 就是鼠标拖∂拽旋转灵敏度
				controls.enableZoom = false // 是否可以缩放
				controls.enablePan = false;
				
				const animate = function() {
					controls.update()
					THREE.$requestAnimationFrame(animate);
					sphere1.rotation.x += 0.01;
					sphere2.rotation.y += 0.01;
					sphere3.rotation.z += 0.01;
					renderer.render(scene, camera);
				};
				animate();
			})
		},
		methods: {
			onTX(e) {
				this.platform.dispatchTouchEvent(e);
			},
			zoomIn: function() {
				if(this.scaleFactor == 1){
					this.camera.position.z = 8;
					this.scaleFactor = 2
				}else if(this.scaleFactor == 2){
					this.camera.position.z = 6;
					this.isNarrow = true
				}
			},
			zoomIn1: function() {
				if(this.scaleFactor == 2){
					this.camera.position.z = 8;
					this.scaleFactor = 1
				}else if(this.scaleFactor == 1){
					this.camera.position.z = 10;
					this.isNarrow = false
				}
			},
			onCanvasTap: function (event) {
				let that = this
			    const spheres = that.spheres;
				const lines = that.lines;
			    
			    // 计算鼠标点击位置
			    const x = event.detail.x;
			    const y = event.detail.y;
			    const rect = wx.createSelectorQuery().select('#myCanvas').boundingClientRect();
			    rect.exec((res) => {
			      mouse.x = (x - res[0].left) / res[0].width * 2 - 1;
			      mouse.y = - (y - res[0].top) / res[0].height * 2 + 1;
			      
			      // 发射一条射线
			      raycaster.setFromCamera(mouse, that.camera);
			      const intersects = raycaster.intersectObjects(spheres, true);
			      
			      if (intersects.length > 0) {
			        const selectedSphere = intersects[0].object;
			        // 随机生成新颜色
			        const newColor = Math.random() * 0xffffff;
			        selectedSphere.material.color.setHex(newColor);
					
					if (!selectedSpheres.includes(selectedSphere)) {
					    selectedSpheres.push(selectedSphere);
						if (selectedSpheres.length === 3) {
							// 连接选中的球体
							const lineGeometry = new THREE.BufferGeometry().setFromPoints([
							  selectedSpheres[0].position,
							  selectedSpheres[1].position,
							  selectedSpheres[2].position
							]);
							const lineMaterial = new THREE.LineBasicMaterial({ 
								color: 0xffffff,
								linewidth: 60,
								linecap: 'round', //ignored by WebGLRenderer
								linejoin:  'round' //ignored by WebGLRenderer
							});
							const line = new THREE.Line(lineGeometry, lineMaterial);
							that.scene.add(line);
				
							// 存储连接线
							that.lines = [...lines, line]
							selectedSpheres = [];
							
							// 更新场景
							that.renderer.render(that.scene, that.camera);
						}
					}
			      }
			    });
			}
		}
	};
</script>
正文到此结束
该篇文章的评论功能已被站长关闭