写在后面,这是第一次发表技术类文章,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);
}
}