需求描述: 模型沿着指定的路线运动,展示如下:
1.html部分
<div class="import_model"></div>
2.js部分
3.导入
<script type="text/javascript" src="libs/Tween.min.js"></script>
<script type="text/javascript" src="libs/three.js"></script>
<script type="text/javascript" src="libs/OrbitControls.js"></script>
2.声明变量,初始化
let scene, mesh, camera, renderer, axesHelper, grid, controls, line;
let group = new THREE.Group();
let pointArr = [
0, 0, -150, 100, 0, -150, 100, 0, -50, 0, 0, -50, 0, 0, 50, 100, 0, 50,
100, 0, 150, 0, 0, 150,
];
var width = window.innerWidth; //窗口宽度
var height = window.innerHeight; //窗口高度
init();
function init() {
// 创建场景
createScene();
// 创建光源
createLight();
// 创建相机
createCamera(width, height);
// 旋转场景动画
createCameraAnimation();
// 创建渲染器
createRender();
// 创建控制器
createControls();
createGrid();
createAxesHelper();
// 以下为场景内东西
// 描绘运动路径
createPath();
// 创建Box
createBox();
// 路径运动
pathFollowRun();
// 渲染
render();
}
3.创建Box
function createBox() {
// 矩形
var geometry = new THREE.BoxGeometry(20, 20, 20);
var material = new THREE.MeshLambertMaterial({
color: 0x009999,
transparent: true, //开启透明度
opacity: 1, //设置透明度
});
mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);
}
4.创建路径
function createPath() {
// 矩形
const geometry = new THREE.BufferGeometry();
// 创建属性缓冲区对象
var attribute = new THREE.BufferAttribute(new Float32Array(pointArr), 3);
// 设置几何体的attributes属性的位置属性
geometry.attributes.position = attribute;
const material = new THREE.LineBasicMaterial({
color: 0x009999,
});
line = new THREE.Line(geometry, material); //线条模型对象
scene.add(line); //线条对象添加到场景中
}
5.沿着路径运动
function pathFollowRun() {
// mesh坐标
var pos = { x: pointArr[0], y: pointArr[1], z: pointArr[2] };
// 所有动画片段tween的集合
var tweenArr = [];
// 批量创建动画片段
for (var i = 0; i < pointArr.length; i += 3) {
var tween = new TWEEN.Tween(pos)
.to({
x: pointArr[i],
y: pointArr[i + 1],
z: pointArr[i + 2],
})
.onUpdate(() => {
mesh.position.x = pos.x;
mesh.position.z = pos.z;
});
tweenArr.push(tween);
}
// 批量连接所有动画片段
for (var i = 0; i < tweenArr.length - 1; i++) {
tweenArr[i].chain(tweenArr[i + 1]);
}
tweenArr[0].start();
}
6.以下为常规搭建场景【可多次复用】
function createScene() {
scene = new THREE.Scene();
}
function createLight() {
//点光源
var point = new THREE.PointLight(0xffffff);
point.position.set(400, 200, 300); //点光源位置
scene.add(point); //点光源添加到场景中
//环境光
// var ambient = new THREE.AmbientLight(0x444444);
var ambient = new THREE.AmbientLight("#ffffff", 1);
scene.add(ambient);
}
function createCamera(width, height) {
var k = width / height; //窗口宽高比
var s = 200; //三维场景显示范围控制系数,系数越大,显示的范围越大
// //创建相机对象
// 正交相机
// camera = new THREE.OrthographicCamera(-s * k, s * k, s, -s, 1, 1000);
// 透视相机(此处需要全景和透视)
camera = new THREE.PerspectiveCamera(
45,
window.innerWidth / window.innerHeight,
0.1,
20000
);
// camera.position.set(200, 300, 200); //设置相机位置
camera.position.set(0, 300, 200); //设置相机位置
camera.lookAt(scene.position); //设置相机方向(指向的场景对象)
}
// 创建相机动画
function createCameraAnimation() {
var obj = {
x: 0,
y: 200,
z: 300,
};
let tween = new TWEEN.Tween(obj);
tween.to(
{
x: 400,
y: 200,
z: 300,
},
5000
);
tween.onUpdate(function () {
// 动态更新相机位置
camera.position.set(obj.x, obj.y, obj.z); //设置相机位置
camera.lookAt(0, 0, 0); //保持相机目标观察点不变
});
tween.start(); //tween动画开始执行
}
function createRender() {
renderer = new THREE.WebGLRenderer();
renderer.setSize(width, height); //设置渲染区域尺寸
// renderer.setClearColor(0xb9d3ff, 1); //设置背景颜色
// renderer.setClearColor(0xffffff, 1); //设置背景颜色
renderer.outputEncoding = THREE.sRGBEncoding; // 模型颜色偏差
renderer.shadowMap.enabled = true; //开启渲染气阴影效果。
document.querySelector(".import_model").appendChild(renderer.domElement);
}
function createControls() {
//创建控件对象 相机对象camera作为参数 控件可以监听鼠标的变化,改变相机对象的属性
controls = new THREE.OrbitControls(camera);
//监听鼠标事件,触发渲染函数,更新canvas画布渲染效果
controls.addEventListener("change", () => {
renderer.render(scene, camera);
});
}
function createGrid() {
grid = new THREE.GridHelper(600, 15, 0xffffff, 0xffffff);
grid.material.opacity = 0.2;
grid.material.depthWrite = false;
grid.material.transparent = true;
scene.add(grid);
}
function createAxesHelper() {
axesHelper = new THREE.AxesHelper(250);
scene.add(axesHelper);
}
function render() {
controls.update();
TWEEN.update(); //更新TWEEN
requestAnimationFrame(render); //请求再次执行渲染函数render,渲染下一帧
renderer.render(scene, camera); //执行渲染操作
}