flyTo方法是在三维场景开发中一个常用的方法,主要用于在控制相机从当前位置,通过差值流畅的运动到目标点,比如在列表中点击某个定位按钮需要将相机飞行到目标点
cesium的flyTo比较复杂,它的相机运动的时候,会计算高度啥的,太低的时候会先升空然后在飞过去再下降,感觉相机的运动轨迹像是一条曲线;在设置参数方面上,除了最主要的目标点和运动时间,还可以设置相机的欧拉角,相机差值时候的差值函数,执行结束后的回调等等;
我们这里就主要实现从当前点运到目标点就行了,运动轨迹为一条直线,可以说是一个乞丐版的flyTo, 要加上欧拉角的话只需要再添加一个动画,因为用的是BABYLON.AnimationGroup,可以实现多个动画
我们这里用js闭包的方式不暴露出执行结束后的动画,在新的动画开始前,停止或者销毁上一个动画
function FlyTo(): (
camera: BABYLON.FreeCamera,
targetPoint: BABYLON.Vector3,
flyDuration: number
) => void {
let currentAnimationGroup: BABYLON.AnimationGroup | null = null;
return function (
camera: BABYLON.FreeCamera,
targetPoint: BABYLON.Vector3,
flyDuration: number
): void {
// 在每次调用前检查并清除之前的动画
if (currentAnimationGroup) {
currentAnimationGroup.stop();
currentAnimationGroup.dispose();
}
// 创建动画组
const animationGroup = new BABYLON.AnimationGroup("cameraAnimationGroup");
currentAnimationGroup = animationGroup;
// 动画:相机位置
const positionAnimation = new BABYLON.Animation(
"positionAnimation",
"position",
60,
BABYLON.Animation.ANIMATIONTYPE_VECTOR3,
BABYLON.Animation.ANIMATIONLOOPMODE_CONSTANT
);
positionAnimation.setKeys([
{ frame: 0, value: camera.position.clone() },
{ frame: flyDuration * 60, value: targetPoint }
]);
animationGroup.addTargetedAnimation(positionAnimation, camera);
// 启动动画组
animationGroup.play(true);
};
}
上一种只是简单的平移相机,我们在上一点强度,加上想相机的欧拉角,这个时候,就是要有两个变量的差值,一个是postition,另一个是rotation,不过这次需要在方法内部访问到scene和camera
const flyTo = (position: BABYLON.Vector3, rotation: BABYLON.Vector3) => {
// 动画:相机位置
const positionAnimation = new BABYLON.Animation(
"positionAnimation",
"position",
2 * 60,
BABYLON.Animation.ANIMATIONTYPE_VECTOR3,
BABYLON.Animation.ANIMATIONLOOPMODE_CONSTANT
);
positionAnimation.setKeys([
{ frame: 0, value: map.camera.position.clone() },
{ frame: 2 * 60, value: position }
]);
// 动画:相机姿态
const rotationAnimation = new BABYLON.Animation(
"rotaionAnimation",
"rotation",
2 * 60,
BABYLON.Animation.ANIMATIONTYPE_VECTOR3,
BABYLON.Animation.ANIMATIONLOOPMODE_CONSTANT
);
rotationAnimation.setKeys([
{ frame: 0, value: map.camera.rotation.clone() },
{ frame: 60, value: rotation }
]);
map.scene.beginDirectAnimation(map.camera, [positionAnimation, rotationAnimation], 0, 2 * 60, false);
}