以下是 three.js 画球体最简单的方法:
<script type="module">
import * as THREE from 'https://esm.sh/three'; // 导入three模块
// 场景、相机和渲染器
const scene = new THREE.Scene(); // 场景
// 透视相机
const camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.z = 5; // 相机位置
const renderer = new THREE.WebGLRenderer({ antialias: true }); // 渲染器
renderer.setSize(window.innerWidth, window.innerHeight); // 渲染范围
document.body.appendChild(renderer.domElement); // 渲染器加入body标签
const sphere = new THREE.SphereGeometry(); // 实例化球体几何体
const material = new THREE.MeshNormalMaterial(); // 实例化材质
const ball = new THREE.Mesh(sphere, material); // 用几何体+材质实例化网格对象(球体)
//ball.rotateX(Math.PI / 4); // 球体X轴旋转45度
scene.add(ball); // 球体加入到场景
renderer.render(scene, camera); // 渲染效果
</script>
<style> body { margin: 0; } </style>
实际绘制球体的JS代码总共也就是10来行,一个有颜色的球体就展现在我们眼前。
细心的朋友可能已经发现:这个球体没有着色,可运行的效果却是一个彩球。嗯,这里我们实例化的 three.js 材质对象是 MeshNormalMaterial,虽然它的名称中有 Normal(正常)一词,它却是一种特殊的材料,法向量(与面垂直的向量)材质,自带光源和颜色,其优点是可以用来快速构建一个3d对象。
画圆球的关键是几何体的创建。three.js 的 SphereGeometry 对象用于创建球形几何体,然后N多的面去填充其表面,因此它实际上有很多配置参数,我们上例都是用了默认配置。在下一个例子,我们将给它配置:半径,水平分段数、垂直分段数、水平起始角、水平扫描角度、垂直起始角、垂直扫描角度等齐整的参数,并用基础材料 MessBasicMaterial 对象构建球形几何体:
<script type="module">
import * as THREE from 'https://esm.sh/three'; // 导入three模块
// 创建场景、相机和渲染器
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// 创建圆球
const total = 8; // 圆球总数
// 实例化球体几何体
const geometry = new THREE.SphereGeometry(2, 32, 32, 0, 2 * Math.PI, 0, 2 * Math.PI);
// 添加 total 个圆球
for (let i = 0; i < total; i++) {
// 实例化球体材质 :基础材质
const material = new THREE.MeshBasicMaterial({
color: Math.random() * 0xffffff, // 随机颜色
transparent: true, // 使用透明度
opacity: 0.8, // 透明度为 0.2
wireframe: true // 使用线框
});
// 实例化网格对象(球 = 几何体+材质)
const ball = new THREE.Mesh(geometry, material);
// 安排下球的位置(根据顺序绕圆心布置)
const radian = (360 / total) * (Math.PI / 180);
ball.position.set(
8 * Math.sin(radian * i),
8 * Math.cos(radian * i),
0
);
scene.add(ball); // ball 加入到场景
}
// 设置相机位置
camera.position.z = 30;
renderer.render(scene, camera);
</script>
<style> body { margin: 0; } </style>
上例我们绘制了 8 个绕圆心排列的线框圆球。之所以使用线框,是因为基础材质 MessBasicMaterial 对象呈现出来的只是一个平面,加入线框球体的观感才可以渲染出来。要绘制更漂亮的球体,需要使用其它材质并配上光源,情况就相对复杂了。
以上两组代码均可存为本地 .html 文档,或将代码拿到 简易编辑器 运行。