Three.js风机旋转

Three.js是基于原生WebGL封装运行的三维引擎,在所有WebGL引擎中,Three.js是国内文资料最多、使用最广泛的三维引擎。使用Three.js可以给前端展示页面增加很多酷炫的效果。

项目需要,想在大屏上加上风力发电机叶片旋转的效果,研究了一点点,我不是专业的前端人员,写起来有点业余,只是简单的把功能实现了,视觉效果方面还需要努力。

风机模型是obj格式的,分了好多个部件,各叶片、柱子都是分开的:

三维模型软件的链接在文章末尾,支持几十种常见的三维模型格式,很方便。

 

效果如下,显示的好看的话还要研究一下光线、材质这些:

代码如下,每个关键点都加了注释了:

<template>
	<div class="VRScene">
		<div id="container"></div>
	</div>
</template>
<script>
	import * as THREE from 'three';
	import { OBJLoader } from 'three/examples/jsm/loaders/OBJLoader';
	var camera;
	var renderer;
	var scene;
	var fans = new THREE.Group();
	var beam = new THREE.Group();

	export default {
		data() {
			return {
				bigImg: require('../assets/pic.jpg')
			}
		},
		mounted() {
			this.$nextTick(() => {
				this.init();
				this.animate();
			})
		},
		methods:{
			init() {
				let container = null
				container = document.getElementById('container');
				// 创建渲染器
				renderer = new THREE.WebGLRenderer();
				renderer.setPixelRatio(window.devicePixelRatio);
				// 设置画布的宽高
				// renderer.setSize(window.innerWidth, window.innerHeight);
				renderer.setSize(window.innerWidth-30, window.innerHeight-200);
				// 判断容器中子元素的长度
				let childs = container.childNodes;
				if (container.childNodes.length > 0) {
					container.removeChild(childs[0]);
					container.appendChild(renderer.domElement);
				} else {
					container.appendChild(renderer.domElement);
				}
				//   container.appendChild(renderer.domElement);

				// 创建场景
				scene = new THREE.Scene();
				// 创建相机
				// camera = new THREE.PerspectiveCamera(100, window.innerWidth / window.innerHeight, 0.1, 100);
				camera = new THREE.PerspectiveCamera(50, (window.innerWidth-30)/(window.innerHeight-200), 0.1, 2000);
				camera.position.set(0, 450, 200);
				camera.up.set(0, -1, 0);
				camera.lookAt(0, 0, 0);

				// 材质、天空盒暂时没用
				var material = new THREE.MeshBasicMaterial(
					// {color: 0xffff00}
				); //材质
				var texture = new THREE.TextureLoader().load(this.bigImg); // 底图
				material.map = texture;
				var skyBox = new THREE.Mesh(
					new THREE.SphereBufferGeometry(100, 32, 32),
					material
				);

				// 平行光源
				var light = new THREE.DirectionalLight();
				light.position.set(0, 1000, 0);
				scene.add(light);
				
				// 环境光
				let ambientLight = new THREE.AmbientLight( 0xffffff, 0.4 );
				scene.add( ambientLight );
				// skyBox.geometry.scale(1, 1, -1);
				// scene.add(skyBox);

				let loader = new OBJLoader();
				loader.load(
					// 路径
					'/static/1.obj',
					// 当模型加载完成(100%)后执行
					(object) => {
						//console.log(object);
						this.object = object;

						var objBbox = new THREE.Box3().setFromObject(object.children[0]);
						// console.log(objBbox);
						// var center = (objBbox.max + objBbox.min) / 2;
						// //var center = object.children[0].

						// getCenter、center方法或属性怎么用不了,只好用这个笨方法
						var cx = (objBbox.max.x + objBbox.min.x) / 2;
						var cy = (objBbox.max.y + objBbox.min.y) / 2;
						var cz = (objBbox.max.z + objBbox.min.z) / 2;

						object.position.y = cy;
						object.position.x = cx;
						object.position.z = cz;

						// 风机叶片group,旋转
						var l0 = this.object.children[0];
						var l1 = this.object.children[1];
						var l2 = this.object.children[2];
						var l3 = this.object.children[5];
						var l4 = this.object.children[6];
						var l5 = this.object.children[7];
						var l6 = this.object.children[8];

						// 柱子group,不动
						var m0 = this.object.children[3];
						var m1 = this.object.children[4];

						// 将各个零件位置移到0点
						l0.position.set(-cx, -cy, -cz);
						l1.position.set(-cx, -cy, -cz);
						l2.position.set(-cx, -cy, -cz);
						l3.position.set(-cx, -cy, -cz);
						l4.position.set(-cx, -cy, -cz);
						l5.position.set(-cx, -cy, -cz);
						l6.position.set(-cx, -cy, -cz);
						m0.position.set(-cx, -cy, -cz);
						m1.position.set(-cx, -cy, -cz);

						// 添加到group中
						fans.add(l0);
						fans.add(l1);
						fans.add(l2);
						fans.add(l3);
						fans.add(l4);
						fans.add(l5);
						fans.add(l6);
						beam.add(m0);
						beam.add(m1);

						// 添加到场景
						scene.add(beam);
						scene.add(fans);

						//scene.add(object);
						renderer.render(scene, camera)
					}
				)

				window.addEventListener('resize', this.onWindowResize, false);
				var bMouseDown = false;
				var x = -1;
				var y = -1;
				// 添加鼠标事件
				container.onmousedown = function(event) {
					event.preventDefault(); //取消默认事件
					x = event.clientX;
					y = event.clientY;
					bMouseDown = true;
				}
				container.onmouseup = function(event) {
					event.preventDefault();
					bMouseDown = false;
				}
				container.onmousemove = function(event) {
					event.preventDefault();
					if (bMouseDown) {
						skyBox.rotation.y += -0.005 * (event.clientX - x);
						skyBox.rotation.x += -0.005 * (event.clientY - y);
						if (skyBox.rotation.x > Math.PI / 2) {
							skyBox.rotation.x = Math.PI / 2
						}
						if (skyBox.rotation.x < -Math.PI / 2) {
							skyBox.rotation.x = -Math.PI / 2
						}
						x = event.clientX;
						y = event.clientY;
					}
				}

				container.onmousewheel = function(event) {
						event.preventDefault();
						if (event.wheelDelta != 0) {
							camera.fov += event.wheelDelta > 0 ? 1 : -1;
							if (camera.fov > 150) {
								camera.fov = 150;
							} else if (camera.fov < 30) {
								camera.fov = 30;
							}
							camera.updateProjectionMatrix();
						}
					},
					container.mouseout = function(event) {
						event.preventDefault();
						bMouseDown = false;
					}
			},
			onWindowResize() {
				// 窗口缩放的时候,保证场景也跟着一起缩放
				// camera.aspect = window.innerWidth / window.innerHeight;
				camera.aspect = window.innerWidth / 500;
				camera.updateProjectionMatrix();
				// renderer.setSize(window.innerWidth, window.innerHeight);
				renderer.setSize(window.innerWidth, 500);
			},
			animate() {
				this.animateId = requestAnimationFrame(this.animate);
				fans.rotation.y -= 0.01;
				//requestAnimationFrame(this.animate);
				renderer.render(scene, camera);
			}

			
		}

	}
</script>

<style scoped>
	#container {
		width: 100%;
		height: 200px;
		margin-top: 200px;
	}

模型load完成事件中可以用,console.log(object)在控制台查看模型零件,然后决定怎么分组:

 代码和模型下载地址,模型是在网上花了好几块钱买的 ^_^ :

代码和模型

三维模型参看软件:

三维模型查看软件

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值