代码拉取完成,页面将自动刷新
<!DOCTYPE html>
<html>
<head>
<title>Threejs实现镜头跟随物体移动效果,镜头拐弯并保持运动方向</title>
<meta charset="UTF-8">
<script type="text/javascript" src="libs/statistics.js"></script>
<script type="text/javascript" src="libs/steak.js"></script>
<script type="text/javascript" src="libs/three.js"></script>
<script type="text/javascript" src="libs/OrbitControls.js"></script>
<script type="text/javascript" src="libs/GLTFLoader.js"></script>
<script type="text/javascript" src="libs/dat.gui.js"></script>
<script type="text/javascript" charset="UTF-8" src="libs/Tween.min.js"></script>
<style>
body {
margin: 0;
overflow: hidden;
}
</style>
</head>
<body>
<div id="dom"></div>
<script type="text/javascript">
var camera;
var renderer;
var mesh;
var curve;
var cube1;
var cube2;
function init() {
// 创建一个场景,它将包含我们所有的元素,如物体,相机和灯光。
var scene = new THREE.Scene();
// 创建一个摄像机,它定义了我们正在看的地方
camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 100000);
// 将摄像机对准场景的中心
camera.position.z = -5746;
camera.position.y = 3289;
camera.position.x = -15945;
camera.lookAt(scene.position);
var orbit = new THREE.OrbitControls(camera);
// 创建一个渲染器并设置大小,WebGLRenderer将会使用电脑显卡来渲染场景
renderer = new THREE.WebGLRenderer({
antialias: true,
logarithmicDepthBuffer: true,
});
renderer.setClearColor(new THREE.Color("#0e0934"));
renderer.setSize(window.innerWidth, window.innerHeight);
var ambientLight = new THREE.AmbientLight("#ffffff", 1);
scene.add(ambientLight);
// 将呈现器的输出添加到HTML元素
document.getElementById("dom").appendChild(renderer.domElement);
// 启动动画
renderScene();
initFeiji();
function initFeiji() {
var loader = new THREE.GLTFLoader();
loader.load('assets/models/feiji/feiji.glb', function(result) {
mesh = result.scene;
mesh.position.set(-1000, -5000, -5000);
scene.add(mesh);
motion()
});
}
function motion() {
// 通过类CatmullRomCurve3创建一个3D样条曲线
curve = new THREE.CatmullRomCurve3([
new THREE.Vector3(-1000, -5000, -5000),
new THREE.Vector3(1000, -5000, 0),
new THREE.Vector3(1800, 800, 1000),
new THREE.Vector3(800, 5000, 5000),
new THREE.Vector3(0, 0, 10000)
]);
// 样条曲线均匀分割100
var points = curve.getPoints(100);
var geometry = new THREE.Geometry();
// 把从曲线轨迹上获得的顶点坐标赋值给几何体
geometry.vertices = points
var material = new THREE.LineBasicMaterial({
color: "#4488ff"
});
var line = new THREE.Line(geometry, material);
scene.add(line);
//管道体
const tubeGeometry = new THREE.TubeGeometry(curve, 100, 500, 30); // 101取点数 3为r 30为三角切面数
const tubeMesh = new THREE.Mesh(tubeGeometry, new THREE.MeshBasicMaterial({
color: "#00aa00",
side: THREE.DoubleSide,
wireframe: true
}))
scene.add(tubeMesh)
}
function changeLookAt(t) {
// 当前点在线条上的位置
const position = curve.getPointAt(t);
var nPos = new THREE.Vector3(position.x, position.y - 100, position.z);
mesh.position.copy(nPos);
// 返回点t在曲线上位置切线向量
const tangent = curve.getTangentAt(t);
// 位置向量和切线向量相加即为所需朝向的点向量
const lookAtVec = tangent.add(nPos);
mesh.lookAt(lookAtVec);
if (t > 0.03) {
var pos = curve.getPointAt(t - 0.03);
camera.position.copy(pos);
camera.lookAt(position)
}
}
var clock = new THREE.Clock(); //声明一个时钟对象
const loopTime = 10 * 1000; // loopTime: 循环一圈的时间
let i = 0;
function renderScene() {
// 使用requestAnimationFrame函数进行渲染
requestAnimationFrame(renderScene);
renderer.render(scene, camera);
if (curve) {
let time = Date.now();
let t = (time % loopTime) / loopTime; // 计算当前时间进度百分比
setTimeout(function() {
changeLookAt(t);
}, 500)
}
}
}
window.onload = init;
// 随着窗体的变化修改场景
function onResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
// 监听窗体调整大小事件
window.addEventListener('resize', onResize, false);
</script>
</body>
</html>
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。