首页IT科技前端工程师职位要求(记录–我在前端干工地(three.js))

前端工程师职位要求(记录–我在前端干工地(three.js))

时间2025-05-01 19:49:55分类IT科技浏览6106
导读:这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助...

这里给大家分享我在网上总结出来的一些知识            ,希望对大家有所帮助

shape上有一个属性表示了孔洞了                   ,接下来就好办了

function createDoorWall() { let { shape } = genwallShape(); const door = new THREE.Path(); //门的位置 door.moveTo(baseWidth / 2 + 5, 0); door.lineTo(baseWidth / 2 + 5, 16); door.lineTo(baseWidth / 2 - 5, 16); door.lineTo(baseWidth / 2 - 5, 0); door.lineTo(baseWidth / 2 + 5, 0); // 形状上的孔洞 shape.holes.push(door); let mesh = createIrregularWall(shape, [ -baseWidth / 2, 0, baseLength / 2 - 1, ]); mesh.name = "带门的墙"; }

调用后如下

可以看到门的形状已经出来了

4            、创建屋顶

这里我们开始创建屋顶      ,首先求出屋顶的宽度      ,也就是我们要创建的几何体的z轴的延展

function createRoof() { //屋顶宽 let width = Math.sqrt((baseWidth / 2) ** 2 + 5 ** 2) + 5;//+5让有一点屋檐的效果 const geometry = new THREE.BoxGeometry(baseLength + 2, width, 1); const texture = new THREE.TextureLoader().load("/img/tile.jpg"); texture.wrapS = texture.wrapT = THREE.RepeatWrapping; texture.repeat.set(2, 2); const material = new THREE.MeshPhongMaterial({ map: texture }); const mesh = new THREE.Mesh(geometry, material); mesh.rotateZ(THREE.MathUtils.degToRad(75)); mesh.rotateY(-Math.PI / 2); mesh.position.set(baseWidth / 3 - 1, 22, 0); mesh.name = "右屋顶"; group.add(mesh); return { roof: mesh, width }; }

方法执行后如下图                   ,我们有了一个右边的屋顶

如法炮制            ,再来一个左边的屋顶

let { roof, width } = createRoof(); return let leftRoof = roof.clone(); leftRoof.rotateX(THREE.MathUtils.degToRad(30)); leftRoof.position.set(-baseWidth / 3 + 1, 22, 0); leftRoof.name = "左屋顶"; group.add(leftRoof);

随后可以在画面中看到如下图      ,我们的房子                   ,哦不            ,准确的说是仓库已经出来了             。                  。      。

5                   、创建门

然后我们开始创建门,门的创建也是用的内置的BoxGeometry几何体             。 添加一个createDoor方法                   ,如下

function createDoor() { //纹理贴图 const texture = new THREE.TextureLoader().load("/img/door.jpg"); //门的大小      、尺寸 const door = new THREE.BoxGeometry(10, 15, 0.5); const material = new THREE.MeshPhongMaterial({ map: texture, transparent: true, opacity: 1, }); const doorMesh = new THREE.Mesh(door, material); doorMesh.name = "门"; doorMesh.position.x = 5; group.add(doorGroup); }

调用后即可看到原本的门洞中出现了一扇门                   ,如下图

6      、为场景添加点击

接下来我想做一点击开门的效果,那么首先要获取到鼠标点击了哪些物体                  。很巧的是three.js为我们提供了一个Raycaster类            ,用来检测射线触碰到了哪些物体      。 添加如下代码

const raycaster = new THREE.Raycaster(); const pointer = new THREE.Vector2(); function onPointerMove(event) { // 将鼠标位置归一化为设备坐标       。x 和 y 方向的取值范围是 (-1 to +1) pointer.x = (event.clientX / width) * 2 - 1; pointer.y = -(event.clientY / height) * 2 + 1; }

然后为canva添加点击事件监听

canvas.addEventListener( "click", () => { const intersects = raycaster.intersectObjects(scene.children); console.log(intersects[0]); console.log("点击了", intersects[0]?.object?.name); }, false );

随后我们点击场景中                   ,在控制台中便能清晰的打印出我们所点击的物体                  。说明:intersectObjects方法会返回射线经过的所有物体组成的数组      ,数组的第0位为离点击区域最近的物体            ,因此可以视为被点击的物体            。

现在已经知道点击的是哪个物体                   ,下面就来添加门的动画效果

7                   、添加关门            、开门动画效果

调整一下对上节的方法      ,如下      ,匹配到点击的物体是门的时候再来触发       。

canvas.addEventListener( "click", () => { const intersects = raycaster.intersectObjects(scene.children); console.log(intersects[0]); console.log("点击了", intersects[0]?.object?.name); if (intersects[0]?.object?.name == "门") { // console.log(intersects[0].object.parent.rotation.y); let speed = 0.05; //再次点击关门 if (intersects[0].object.parent.rotation.y <= -2.5) { // console.log("关门"); let a = setInterval(() => { if (intersects[0].object.parent.rotation.y >= 0) { intersects[0].object.parent.rotation.y = 0; clearInterval(a); return; } intersects[0].object.parent.rotation.y += speed; }, 1000 / 60); } else { // console.log("开门"); let a = setInterval(() => { if (intersects[0].object.parent.rotation.y <= -2.5) { clearInterval(a); return; } intersects[0].object.parent.rotation.y -= speed; }, 1000 / 60); } } }, false );

这样就能正确的运行了吗?当然不                   ,上述代码中让门以y轴做旋转            ,但是在three.js中      ,物体的旋转轴为物体的中心                   ,因此我们需要改变一下门的旋转轴            ,使之在视觉上呈现出以旋转中心的改变,下面改造一下createDoor方法                   ,如下                   ,

//创建门 function createDoor() { const texture = new THREE.TextureLoader().load("/img/door.jpg"); const door = new THREE.BoxGeometry(10, 15, 0.5); const material = new THREE.MeshPhongMaterial({ map: texture, transparent: true, opacity: 1, }); const doorMesh = new THREE.Mesh(door, material); // doorMesh.rotateY(Math.PI / 2); // doorMesh.position.set(-baseLength / 2, 7, 0); doorMesh.name = "门"; //以下代码做出了更改 const doorGroup = new THREE.Group();//添加一个门的父级 doorGroup.name = "门的包裹"; doorGroup.position.set(-5, 8, baseLength / 2);//通过父级来改变门的旋转轴 //现在这个是相对于父级 doorMesh.position.x = 5; doorGroup.add(doorMesh); group.add(doorGroup); return doorGroup; }

改造完后点击门,会发现门绕着预期的旋转轴打开了                   。如下图

四      、创建天空盒

这里的天空盒非常的简单            。使用内置的SphereGeometry几何体创建一个与地面半径一致的圆            ,然后载入贴图

//天空盒 function createSkyBox() { const texture = new THREE.TextureLoader().load("/img/sky.jpg"); texture.wrapS = texture.wrapT = THREE.RepeatWrapping; // texture.repeat.set(1, 1); const skyBox = new THREE.SphereGeometry(500, 100, 100); const material = new THREE.MeshPhongMaterial({ map: texture, side: THREE.BackSide, }); const skyBoxMesh = new THREE.Mesh(skyBox, material); scene.add(skyBoxMesh); }

最终呈现出的效果如下图

在最后你通过循环多创建几个房子                   ,像这样

或者查看文档切换成第一人称控制器在自己创建的场景中遨游。

本文转载于:

https://juejin.cn/post/7200571354926858301

如果对您有所帮助      ,欢迎您点个关注            ,我会定时更新技术文档                   ,大家一起讨论学习      ,一起进步                   。

声明:本站所有文章      ,如无特殊说明或标注                   ,均为本站原创发布                  。任何个人或组织            ,在未征得本站同意时      ,禁止复制                   、盗用            、采集、发布本站内容到任何网站                   、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益                   ,可联系我们进行处理             。

创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!

展开全文READ MORE
seo怎样才能优化网站(seo教程网站优化) 锦州ip(锦州资讯网)