使用cesium使用飞行漫游功能以及原地平滑转向

4 篇文章 0 订阅
4 篇文章 0 订阅

在cesium里面实现飞行漫游,由于没有找到合适的案例,自力更生,丰衣足食。

相机的移动主要两种方式:

setView,flyTo

其中flyTo测试了,感觉不合适,所以用了setView,当然只是自己的浅薄认识,如有错误,敬请指正。

废话不多说了,直接上代码,基本都能看懂吧,我尽量写了注释了。

另外代码和环境我都上传了,地址:https://download.csdn.net/download/dragonrxl/11579847

<!DOCTYPE html>
<html lang="en">
<head>
  <!-- Use correct character set. -->
  <meta charset="utf-8">
  <!-- Tell IE to use the latest, best version. -->
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <!-- Make the application on mobile take up the full browser screen and disable user scaling. -->
  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">
  <title>cisium airplane trip</title>
  <script src="Build/Cesium/Cesium.js"></script>
  <style>
      @import url(Build/Cesium/Widgets/widgets.css);
      html, body, #cesiumContainer {
          width: 100%; height: 100%; margin: 0; padding: 0; overflow: hidden;
      }
	  .cesium-widget-credits{ display:none} /**  隐藏版权信息 **/
	  .cesium-viewer .cesium-widget-credits{ display:none }
  </style>
</head>
<body>
  <div id="cesiumContainer"></div>
  <script>
    var viewer = new Cesium.Viewer('cesiumContainer', {
		geocoder: false,//是否显示geocoder小器件,右上角查询按钮
		homeButton:false,//是否显示Home按钮
		sceneModePicker:false,//是否显示3D/2D选择器
		baseLayerPicker:false,//是否显示图层选择器
		navigationHelpButton:false,//是否显示右上角的帮助按钮
		animation:false,//是否创建动画小器件,左下角仪表
		creditContainer:"cesiumContainer",// 对应上面div的ID
		timeline:false,//是否显示时间轴
		fullscreenButtion:false,//是否显示全屏按钮
		vrButton:false,
		selectionIndicator : false,//是否显示选取指示器组件
	});
	// 上面配置选项可以控制部分控件是否显示
	viewer.scene.debugShowFramesPerSecond = true;// 显示帧率
	/** 默认使用bing地图,转换为google地图开始 **/
	var google = new Cesium.UrlTemplateImageryProvider({
		url : 'http://mt0.google.cn/vt/lyrs=s&hl=zh-CN&x={x}&y={y}&z={z}',
		tilingScheme : new Cesium.WebMercatorTilingScheme(),
		maximumLevel : 20
	});
	viewer.imageryLayers.addImageryProvider(google);
	/** 默认使用bing地图,转换为google地图结束 **/
		
	/** 相机视角飞行 开始 **/
	var marks = [
		{lng: 116.812948,lat:36.550064, height:100, flytime:15},// height:相机高度(单位米) flytime:相机两个标注点飞行时间(单位秒)
		{lng: 116.812948,lat:36.560064, height:100, flytime:15},
		{lng: 116.802948,lat:36.560064, height:100, flytime:15},
		{lng: 116.802948,lat:36.550064, height:100, flytime:15},
	];// 地标集合 根据地标顺序来进行漫游
	var marksIndex = 1;
	var pitchValue = -20;

	viewer.scene.camera.flyTo({
		destination: Cesium.Cartesian3.fromDegrees(marks[0].lng,marks[0].lat, marks[0].height),  //定位坐标点,建议使用谷歌地球坐标位置无偏差
		duration:7   //定位的时间间隔
	});
	
	setTimeout(function(){
		 flyExtent();
	},7000);
	
	function  flyExtent(){
		// 相机看点的角度,如果大于0那么则是从地底往上看,所以要为负值
		var pitch = Cesium.Math.toRadians(pitchValue);
		// 时间间隔2秒钟
		setExtentTime(marks[marksIndex].flytime);
		var Exection = function TimeExecution() {
			var preIndex = marksIndex - 1;
			if(marksIndex == 0){
				preIndex = marks.length -1;
			}
			var heading = bearing(marks[preIndex].lat, marks[preIndex].lng, marks[marksIndex].lat, marks[marksIndex].lng);
			heading = Cesium.Math.toRadians(heading);
			// 当前已经过去的时间,单位s
			var delTime = Cesium.JulianDate.secondsDifference(viewer.clock.currentTime, viewer.clock.startTime);
			var originLat = marksIndex == 0 ? marks[marks.length - 1].lat : marks[marksIndex-1].lat;
			var originLng = marksIndex == 0 ? marks[marks.length - 1].lng : marks[marksIndex-1].lng;
			var endPosition = Cesium.Cartesian3.fromDegrees(
				(originLng+(marks[marksIndex].lng-originLng)/marks[marksIndex].flytime*delTime), 
				(originLat+(marks[marksIndex].lat-originLat)/marks[marksIndex].flytime*delTime), 
				marks[marksIndex].height
			);
			viewer.scene.camera.setView({
				destination: endPosition,
				orientation: {
					heading: heading,
					pitch : pitch,
				}
			});
			if (Cesium.JulianDate.compare(viewer.clock.currentTime, viewer.clock.stopTime) >= 0) {
				viewer.clock.onTick.removeEventListener(Exection);
				changeCameraHeading();
			}
		};
		viewer.clock.onTick.addEventListener(Exection);
	}
	// 相机原地定点转向
	function  changeCameraHeading(){
		var nextIndex = marksIndex + 1;
		if(marksIndex == marks.length - 1){
			nextIndex = 0;
		}
		// 计算两点之间的方向
		var heading = bearing(marks[marksIndex].lat, marks[marksIndex].lng, marks[nextIndex].lat, marks[nextIndex].lng);
		// 相机看点的角度,如果大于0那么则是从地底往上看,所以要为负值
		var pitch = Cesium.Math.toRadians(pitchValue);
		// 给定飞行一周所需时间,比如10s, 那么每秒转动度数
		var angle = (heading - Cesium.Math.toDegrees(viewer.camera.heading)) / 2;
		// 时间间隔2秒钟
		setExtentTime(2);
		// 相机的当前heading
		var initialHeading = viewer.camera.heading;
		var Exection = function TimeExecution() {
			// 当前已经过去的时间,单位s
			var delTime = Cesium.JulianDate.secondsDifference(viewer.clock.currentTime, viewer.clock.startTime);
			var heading = Cesium.Math.toRadians(delTime * angle) + initialHeading;
			viewer.scene.camera.setView({
				orientation: {
					heading : heading,
					pitch : pitch,
				}
			});
			if (Cesium.JulianDate.compare(viewer.clock.currentTime, viewer.clock.stopTime) >= 0) {
				viewer.clock.onTick.removeEventListener(Exection);
				marksIndex = ++marksIndex >= marks.length ? 0 : marksIndex;
				flyExtent();
			}
		};
		viewer.clock.onTick.addEventListener(Exection);
	}
	// 设置飞行的时间到viewer的时钟里
	function setExtentTime(time){
		var startTime = Cesium.JulianDate.fromDate(new Date());
		var stopTime = Cesium.JulianDate.addSeconds(startTime, time, new Cesium.JulianDate());
		viewer.clock.startTime = startTime.clone();  // 开始时间
		viewer.clock.stopTime = stopTime.clone();     // 结速时间
		viewer.clock.currentTime = startTime.clone(); // 当前时间
		viewer.clock.clockRange = Cesium.ClockRange.CLAMPED; // 行为方式
		viewer.clock.clockStep = Cesium.ClockStep.SYSTEM_CLOCK; // 时钟设置为当前系统时间; 忽略所有其他设置。
	}
	/** 相机视角飞行 结束 **/
	
	/** 飞行时 camera的方向调整(heading) 开始 **/
	 // Converts from degrees to radians.
	function toRadians(degrees) {
		return degrees * Math.PI / 180;
	}

	// Converts from radians to degrees.
	function toDegrees(radians) {
		return radians * 180 / Math.PI;
	}

	function bearing(startLat, startLng, destLat, destLng){
		startLat = this.toRadians(startLat);
		startLng = this.toRadians(startLng);
		destLat = this.toRadians(destLat);
		destLng = this.toRadians(destLng);

		let y = Math.sin(destLng - startLng) * Math.cos(destLat);
		let x = Math.cos(startLat) * Math.sin(destLat) - Math.sin(startLat) * Math.cos(destLat) * Math.cos(destLng - startLng);
		let brng = Math.atan2(y, x);
		let brngDgr = this.toDegrees(brng);
		return (brngDgr + 360) % 360;
	}
	/** 飞行时 camera的方向调整(heading) 结束 **/
  </script>
</body>
</html>

 

  • 16
    点赞
  • 42
    收藏
    觉得还不错? 一键收藏
  • 28
    评论
以下是使用 Cesium 实现飞行漫游效果的源码示例: ```html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Cesium Flyover</title> <script src="https://cesium.com/downloads/cesiumjs/releases/1.82/Build/Cesium/Cesium.js"></script> <link rel="stylesheet" href="https://cesium.com/downloads/cesiumjs/releases/1.82/Build/Cesium/Widgets/widgets.css"> <style> html, body, #cesiumContainer { width: 100%; height: 100%; margin: 0; padding: 0; overflow: hidden; } </style> </head> <body> <div id="cesiumContainer"></div> <script> Cesium.Ion.defaultAccessToken = 'YOUR_CESIUM_ION_TOKEN'; var viewer = new Cesium.Viewer('cesiumContainer', { terrainProvider: Cesium.createWorldTerrain(), shouldAnimate: true }); var camera = viewer.camera; camera.flyTo({ destination: Cesium.Cartesian3.fromDegrees(-75.59777, 40.03883, 200000.0), orientation: { heading: Cesium.Math.toRadians(0.0), pitch: Cesium.Math.toRadians(-90.0), roll: 0.0 }, duration: 5 }); </script> </body> </html> ``` 在这个示例中,我们使用Cesium 提供的 `Viewer` 类来创建一个基本的地球场景,并使用 `camera.flyTo()` 方法来实现飞行漫游效果。在 `flyTo()` 中,我们可以指定我们想要去的目的地的经纬度坐标,以及相机的朝向、倾斜度和飞行的持续时间。这个示例中我们使用了一个较简单的目的地坐标(费城),但你可以根据自己的需要修改。 需要注意的是,我们在使用 Cesium 的时候需要提供一个 Cesium Ion 访问令牌(`YOUR_CESIUM_ION_TOKEN`)。你需要在 Cesium Ion 网站上注册账户并获取访问令牌,然后将访问令牌替换到上述代码中的 `YOUR_CESIUM_ION_TOKEN`。 希望这个示例对你有所帮助!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 28
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值