送你一个甜甜圈|大帅老猿threejs特训

写在前面,这是第一次发表技术类文章,2022年本来给自己定了一个目标在掘金发表10 篇 技术类的文章。结果反正因为各种各样的原因,导致最后也没有完成,甚至都没有开始。2022年产出为0。这一次实战课程起因是在群里看到胖达老师做了一单,那金额着实让我羡慕呀。然后就在千呼万唤中,胖达老师准备出一个教程,带领大家入门之后并会出大教程,带领大家丰富致富手段。

当然其实这次决定来写这个文章还有一个决定性的因素,群里的大佬天天打卡完成了文章,就比你厉害的大佬还比你勤劳,还在学习。就瞬间感觉自己也要迈出这第一步的。就平时可能也是知道大佬们都是很努力,但是其实我都没看到。这一次那属于天天都看到了,刺激的更明显。也谢谢群里的各位大佬们。

第一次写技术文章如果写的不好,或者怎么改进的,希望路过的前辈们给予指点!!!

效果图

我看到第一反应是上来就这个难度???这我只是一个Three的小白,上来就让我跑,不太适合吧!当然可能可能只有我的反应是这样的。当然毕竟是个程序员,不能被唬倒(工作中奇奇怪怪的需求也不是没有碰到过)。所以接下来我们来分析一下需求,来看下怎么完成这个效果。

分析

首先这个动图,有几个东西,

  • 第一个背景这个应该是通过类似背景图的方式来加载进来的,所以这个应该不麻烦。
  • 第二个会转的盘子还是有花纹的,这个旋转应该Three.js 里面有对应的api吧,花纹也是背景图吧。
  • 第三个那个装甜甜圈的盘子,还有6个甜甜圈,还各自都是自动掉落,这要怎么做呀

以上是我看到这个东西后,第一反应

然后胖达老师在之后讲解过程中说,首先我们去3D模型网站(这里写网址)下载一个甜甜圈的模型。当然这个不能说找到非常符合自己需求的模型图,这时候我们下载一个本体,然后用Blender 这个软件进行对模型的修改。来改成自己所需要使用的模型样子。处理好模型后,接下来就是我们要搭建运行环境(Three.js 的安装可以参考官网的文档 放地址)那么接下来就来介绍一下怎么制作

开始

首先要有基础场景三大件

  • scene:场景 new THREE.Scene();
  • camera:相机 new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.01, 10)
  • renderer: 渲染器 new THREE.WebGLRenderer()

三大件都有了之后那么就要给renderer渲染器设置一下大小,然后把渲染器添加到页面里,再来设置一下相机的位置。这是我们创建一个盒子模型。放进场景,开启祯循环在当中把场景和相机初始化进去。这时候我们来看下效果,就是会出现一个绿色的方块可以根据我们的鼠标随意进行旋转、放大缩小。可以控制物体。

案例代码

这时候还是在漆黑的夜里,我们加载一下环境光HDR图片:RGBELoader

是不是现在一下子就感觉对了,效果也和最开始的差不多,环境有了,现在就是把我们创建的盒子换成甜甜圈模式就完成了效果了,话不多说,马上来加载甜甜圈模型。当当当,最后的效果就出来了。

END


个人踩坑

  • 首先是类型问题,three没有像TS那样如果类型错了,就给你报错,在控制台也很正常也没爆红,不像我们平时写业务代码,如果代码上有问题,控制台是直接报错,会给你错误提示,three 只能你自己进行排查,你在前面都可以,突然在这里不行了,或者你在本地测试都可以,和后端联调时,突然发现自己的效果变没了,这时候可以看下是不是接口返回的数据类型错误。
  • 因为Three.js 是3D的,所以有时候一开始我们还不熟练的时候,相机位置经常没有放对,然后你的代码都没有写错,但是看效果的时候,直接看不到东西,这时候你会蒙了,什么情况,我是不是不适合学这个之类的想法,你可以鼠标滚轮放大缩小看看,效果能不能处来,是效果本身确实有问题,还是你的相机初始位置的问题。
  • Three.js 是慢工出细活,可能大家都是用了同样的API,同样的代码,但是人家在那边调了许久的参数,出来的效果可能就是很好看,或者说很真实。这个也没捷径,只能是慢慢调。当然可能有只是我不知道。

结语

终于写完了自己第一篇的技术文章,开始了第一步,先给自己鼓个掌。这一篇只是稍微介绍了Three.js 基本的API,以及做了一个小demo。后面打算在写一篇,从Blender 软件中建模开始,建设一个基础模型,然后布置一下。找个人物。让这个人物可以在场馆里游历。一个元宇宙的雏形,因为涉及建模的操作,所以打算会录制一个视频放在B站,仅供参考,毕竟我也是新手。(本来是想写在一篇的,但是觉得篇幅太长,看的累,其次我也有私心,怕自己第一篇写完又停下了,没有写,所以还是多写下,让自己习惯写文章的习惯)。

熟能生巧,你学会了,不代表你理解了,当你用你的语言说出来,让其他人听懂了,这才是说明你真的掌握这个知识、技能了。

可以直接上B站搜索 Web3D胖达 有三天打卡营的直播回放视频,当然比我这个讲的细致,讲的好了。

当然最后还是要谢谢大帅老师(知道于开课吧的前端全栈课程)和胖达老师(知道于群里发放收益时),不止教了知识,还让我迈出了写文章的第一步,希望2023年,可以完成发10篇技术文章的fiag。欢迎加入猿创营 (v:dashuailaoyuan),一起交流学习。

案例代码

import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls';
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader';
import { RGBELoader } from 'three/examples/jsm/loaders/RGBELoader';

let mixer;

const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.01, 10);
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);

camera.position.set(0.5, 0.4, 0.7);

const controls = new OrbitControls(camera, renderer.domElement);

// 创建环境光,有光了才亮了
const ambientLight = new THREE.AmbientLight(0xffffff, 0.3);
scene.add(ambientLight);

const directionLight = new THREE.DirectionalLight(0xffffff, 0.4);
scene.add(directionLight);

let donuts;
new GLTFLoader().load('../resources/models/donuts.glb', (gltf) => {
    scene.add(gltf.scene);
    donuts = gltf.scene;
    mixer = new THREE.AnimationMixer(gltf.scene);
    const clips = gltf.animations; // 播放所有动画
    clips.forEach(function (clip) {
        const action = mixer.clipAction(clip);
    action.loop = THREE.LoopOnce;
    // 停在最后一帧
    action.clampWhenFinished = true;
    action.play();
    });
});

new RGBELoader().load('../resources/sky.hdr', function (texture) {
    scene.background = texture;
    texture.mapping = THREE.EquirectangularReflectionMapping;
    scene.environment = texture;
    renderer.outputEncoding = THREE.sRGBEncoding;
    renderer.render(scene, camera);
});

/*
* 祯循环
*/
animate();
function animate() {
    requestAnimationFrame(animate);
    renderer.render(scene, camera);
    controls.update();
    if (donuts) {
        donuts.rotation.y += 0.01;
    }
    if (mixer) {
        mixer.update(0.02);
    }
}

你可能感兴趣的:(前端three.js)