「这是我参与2022首次更文挑战的第6天,活动详情查看:2022首次更文挑战」
示例代码采用three.js-r73版本:cdnjs.cloudflare.com/ajax/libs/t…
注:之前的文章《ThreeJs 入门01-编写第一个three.js程序》应该是02,有时间再写下01
我们之前写的代码,都是在一段脚本中完成,逻辑复杂后,比较难读懂。我们将其按照功能拆分成函数,进行封装调用
重新定义html
- 我们定义一个高600px、宽为100%、 id 为
canvas-frame
的元素 - 当页面加载完成后,把我们要渲染的场景,添加到这个元素中。
<style type="text/css">
div#canvas-frame {
border: none;
cursor: pointer;
width: 100%;
height: 600px;
background-color: #EEEEEE;
}
</style>
<body onload="threeStart();">
<div id="canvas-frame"></div>
</body>
编写js脚本
threeStart
作为页面加载完成之后执行入口,我们需要依次实现
- initThree 初始化渲染函数
- initCamera 初始化摄像机
- initScene 初始化场景
- initLight 初始化平行光
- initObject 初始化几何体
- render 渲染场景
function threeStart(){
initThree();
initCamera();
initScene();
initLight();
initObject();
render();
}
initThree 初始化渲染函数
- 我们获取
canvas-frame
元素的宽度和高度,用来计算画布和场景大小 - 初始化渲染器时,开启
antialias
,渲染器会通过更好的一个算法,把我们的图像计算的更清晰。效果,可以看下图- 设置为true,会占用更多的 gpu 资源。大数据量时,我们设置为false,提高性能
抗锯齿前
抗锯齿后
效果提升了不少
- 渲染器创建好后,把我们的渲染器添加到
canvas-frame
元素中 - 设置清除颜色
setClearColor
,当我们绘制每一帧的时候,我们会用灰色或者白色,把画布刷新一下,重新绘制- 如果不重新绘制,会造成重复效果
var width,height
var renderer;
function initThree() {
width = document.getElementById("canvas-frame").clientWidth;
height = document.getElementById("canvas-frame").clientHeight;
renderer = new THREE.WebGLRenderer({
antialias: true, // 是否开启反锯齿,设置为true开启反锯齿,可以提升画质
});
renderer.setSize(width, height); // 设置画布大小
document.getElementById("canvas-frame").appendChild(renderer.domElement); // 将画布添加到页面上
renderer.setClearColor(0xffffff, 1.0); // 设置画布颜色
}
initCamera 初始化摄像机
- 使用正投影相机,最近为1,最远为1000
- 相机的位置,放在y轴 1000 的位置,类似于在空中
camera.lookAt
通过这个属性,让物体一直面朝摄像机
var camera;
function initCamera(){
camera = new THREE.PerspectiveCamera(45, width/height, 1, 10000)
// 表示对象局部位置的Vector3。默认值为(0, 0, 0)。
camera.position.x = 0
camera.position.y = 1000
camera.position.z = 0
// up 这个属性由lookAt方法所使用,例如,来决定结果的朝向。
camera.up.x = 0
camera.up.y = 0
camera.up.z = 1
// 旋转物体使其在世界空间中面朝一个点。
// 这一方法不支持其父级被旋转过或者被位移过的物体。
camera.lookAt({
x:0,
y:0,
z:0
})
}
initScene 初始化场景
- 我们初始化场景,不需要做什么操作
var scene;
function initScene() {
scene = new THREE.Scene();
}
initLight 初始化平行光
- 平行光是沿着特定方向发射的光。这种光的表现像是无限远,从它发出的光线都是平行的。
- 常常用平行光来模拟太阳光的效果;
- 太阳足够远,因此我们可以认为太阳的位置是无限远,所以我们认为从太阳发出的光线也都是平行的。
var light;
function initLight() {
// 定义平行光
light = new THREE.DirectionalLight(0xff0000, 1.0, 0);
// 设置平行光位置
light.position.set(100, 100, 200);
// 将平行光添加到场景
scene.add(light);
}
- color - (可选参数) 16进制表示光的颜色。 缺省值为 0xffffff (白色)。
- intensity - (可选参数) 光照的强度。缺省值为1
initObject 初始化几何体
var cube;
function initObject() {
// 创建几何体
var geometry = new THREE.Geometry();
// 创建线的材质
var material = new THREE.LineBasicMaterial({
vertexColors: THREE.VertexColors, // 使用顶点颜色
});
// 定义颜色,用来表示端点的颜色
var color1 = new THREE.Color(0x444444),
color2 = new THREE.Color(0xff0000);
// 线的材质可以由2个端点的颜色决定
var p1 = new THREE.Vector3(-100, 0, 1000);
var p2 = new THREE.Vector3(1000, 0, -100);
// 把两个端点添加到几何体中
geometry.vertices.push(p1);
geometry.vertices.push(p2);
// 把颜色添加到几何体中,与顶点数量对应
geometry.colors.push(color1, color2);
// 创建线
var line = new THREE.Line(geometry, material, THREE.LinePieces);
scene.add(line);
}
- 我们这里创建了一条线
- 我们这里使用了顶点颜色vertexColors: THREE.VertexColors,就是线条的颜色会根据顶点来计算。
- 然后定义了两个颜色,用来表示两个端点的颜色
- 把两个顶点添加到几何体中
- geometry中colors表示顶点的颜色,必须材质中vertexColors等于
THREE.VertexColors
时,颜色才有效,如果vertexColors等于THREE.NoColors
时,颜色就没有效果了。那么就会去取材质中color的值,这个很重要
render 渲染场景
- 每次渲染场景之前,先对场景进行清空
renderer.clear
通过setClearColor值,来对场景进行刷新- 刷新完之后再进行渲染
function render() {
renderer.clear(); // 通过setClearColor值,来对场景进行刷新
renderer.render(scene, camera);
requestAnimationFrame(render);
}
至此我们的代码重构就完成了,实现效果