TrackRoam.js 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320
  1. /* 引入Cesium */
  2. // import * as Cesium from 'Cesium';
  3. /**
  4. * 飞行漫游
  5. */
  6. class TrackRoam {
  7. /**
  8. * 默认初始化
  9. * @param {Object} viewer 三维场景
  10. */
  11. constructor(viewer) {
  12. if (!viewer) throw new Cesium.DeveloperError('no viewer object!');
  13. this._viewer = viewer;
  14. this._draw3DObj = null;
  15. }
  16. /**
  17. * 飞行漫游路径
  18. * @ignore 忽略注释,注释不生成Doc
  19. * @param pathsData
  20. */
  21. _startFly(pathsData, options) {
  22. var _self = this;
  23. options = options || {};
  24. options.time = Cesium.defaultValue(options.time, 360);
  25. options.isPathShow = Cesium.defaultValue(options.isPathShow, true);
  26. options.height = Cesium.defaultValue(options.height, 5);
  27. options.role = Cesium.defaultValue(options.role, 1);
  28. this.url = options.modelUrl;
  29. this.time = options.time;
  30. this.isPathShow = options.isPathShow;
  31. this.height = options.height;
  32. this.role = options.role;
  33. _self.clearFlyPaths();
  34. _self._viewer.camera.setView({
  35. destination: pathsData.position,
  36. orientation: pathsData.orientation,
  37. });
  38. setTimeout(function() {
  39. executeFly3D();
  40. }, 200);
  41. function executeFly3D() {
  42. if (pathsData && pathsData.geometry) {
  43. var positionA = pathsData.geometry.coordinates;
  44. /* 转换坐标 */
  45. let positions = positionA.map(point => {
  46. return Cesium.Cartesian3.fromDegrees(point.lng, point.lat, point.height);
  47. });
  48. //总距离
  49. let distance = [];
  50. for (let i = 0; i < positions.length - 1; i++) {
  51. let dis = Cesium.Cartesian3.distance(positions[i], positions[i + 1])
  52. distance.push(dis)
  53. }
  54. //点与点之间间隔时间
  55. let times = [Cesium.JulianDate.fromDate(new Date())]
  56. times.push(Cesium.JulianDate.addSeconds(times[0], _self.time, new Cesium.JulianDate()))
  57. for (let i = 1; i < positions.length - 1; i++) {
  58. let s = Cesium.JulianDate.addSeconds(times[i], _self.time * (distance[i] / distance[0]), new Cesium.JulianDate())
  59. times.push(s)
  60. }
  61. //一种属性,其值在给定时间内从提供的样本集和指定的插值算法和插值度中插值。
  62. let oriSamples = new Cesium.SampledProperty(Cesium.Cartesian3);
  63. oriSamples.addSamples(times, positions);
  64. let startTime = times[0]; // 起始时间
  65. let stopTime = times[times.length - 1]; // 结束时间
  66. _self._viewer.clock.startTime = startTime.clone(); // 设置始时钟始时间
  67. _self._viewer.clock.stopTime = stopTime.clone(); // 设置始终停止时间
  68. _self._viewer.clock.currentTime = startTime.clone(); // 设置时钟当前时间
  69. _self._viewer.clock.clockRange = Cesium.ClockRange.LOOP_STOP; //循环执行
  70. _self._viewer.clock.multiplier = 10; // 时间速率,数字越大时间过的越快
  71. // 计算提供的实例之间的天数差。
  72. let timeOfResolution = 6;
  73. let samplesNum = Math.floor(
  74. Cesium.JulianDate.secondsDifference(stopTime, startTime) / timeOfResolution
  75. );
  76. let sampledPositions = [];
  77. let sampledTimes = [];
  78. for (let i = 0; i < samplesNum + 1; i++) {
  79. let sampleTime = Cesium.JulianDate.addSeconds(
  80. startTime,
  81. i * timeOfResolution,
  82. new Cesium.JulianDate()
  83. );
  84. let tmpPos = oriSamples.getValue(sampleTime);
  85. sampledPositions.push(Cesium.Cartographic.fromCartesian(tmpPos));
  86. sampledTimes.push(sampleTime);
  87. }
  88. let promise = Cesium.sampleTerrainMostDetailed(
  89. _self._viewer.terrainProvider,
  90. sampledPositions
  91. ).then(() => {
  92. let carPositionProperty = new Cesium.SampledPositionProperty();
  93. //高度
  94. for (let i = 0; i < sampledPositions.length; i++) {
  95. sampledPositions[i].height = sampledPositions[i].height + _self.height
  96. }
  97. for (let i = 0; i < samplesNum + 1; i++) {
  98. carPositionProperty.addSample(
  99. sampledTimes[i],
  100. Cesium.Ellipsoid.WGS84.cartographicToCartesian(sampledPositions[i])
  101. );
  102. }
  103. var position = carPositionProperty;
  104. _self.entityFly = _self._viewer.entities.add({
  105. // 和时间轴关联
  106. availability: new Cesium.TimeIntervalCollection([
  107. new Cesium.TimeInterval({
  108. start: startTime,
  109. stop: stopTime,
  110. }),
  111. ]),
  112. // 位置
  113. position: position,
  114. //基于位置移动自动计算方向.
  115. orientation: new Cesium.VelocityOrientationProperty(position),
  116. point: {
  117. color: Cesium.Color.RED,
  118. outlineColor: Cesium.Color.WHITE,
  119. outlineWidth: 2,
  120. pixelSize: 10,
  121. },
  122. //路径
  123. path: {
  124. show: _self.isPathShow,
  125. resolution: 1,
  126. //设置航线样式,线条颜色,内发光粗细,航线宽度等
  127. material: new Cesium.PolylineGlowMaterialProperty({
  128. glowPower: 0.1,
  129. color: Cesium.Color.YELLOW,
  130. }),
  131. width: 10,
  132. },
  133. });
  134. // 0自由模式 1跟随模式 2第一视角 3 第三视角
  135. if (_self.role == 0) {
  136. } else if (_self.role == 1) {
  137. _self._viewer.trackedEntity = _self.entityFly;
  138. } else if (_self.role == 2) {
  139. _self._viewer.trackedEntity = _self.entityFly;
  140. let exection = function TimeExecution() {
  141. if (_self._viewer.clock.shouldAnimate === true) {
  142. //获取位置
  143. let center = _self.entity.position.getValue(
  144. _self._viewer.clock.currentTime
  145. );
  146. //获取偏向角
  147. let orientation = _self.entity.orientation.getValue(
  148. _self._viewer.clock.currentTime
  149. )
  150. let transform = Cesium.Transforms.eastNorthUpToFixedFrame(center);
  151. transform = Cesium.Matrix4.fromRotationTranslation(Cesium.Matrix3.fromQuaternion(orientation), center);
  152. _self._viewer.camera.lookAtTransform(transform, new Cesium.Cartesian3(-50, 0, 250))
  153. }
  154. };
  155. //监听时间变化 让cesium的时钟方法来监听该方法
  156. _self._viewer.clock.onTick.addEventListener(exection);
  157. } else if (_self.role == 3) {
  158. _self._viewer.trackedEntity = _self.entityFly;
  159. let exection = function TimeExecution() {
  160. if (_self._viewer.clock.shouldAnimate === true) {
  161. //获取位置
  162. let center = _self.entity.position.getValue(
  163. _self._viewer.clock.currentTime
  164. );
  165. // 更新相机位置(上帝视角)
  166. _self._viewer.camera.lookAt(center, new Cesium.Cartesian3(0, 0, 1000))
  167. }
  168. };
  169. //监听时间变化 让cesium的时钟方法来监听该方法
  170. _self._viewer.clock.onTick.addEventListener(exection);
  171. }
  172. });
  173. } else {
  174. return;
  175. }
  176. }
  177. }
  178. }
  179. /**
  180. * 通用对外公开函数
  181. */
  182. Object.assign(TrackRoam.prototype, /** @lends TrackRoam.prototype */ {
  183. /**
  184. * 设定飞行漫游路线
  185. */
  186. drawFlyPaths(coordinates, options) {
  187. //异步函数
  188. return new Promise((resolve, reject) => {
  189. let _self = this;
  190. //清除飞行路线
  191. _self.clearFlyPaths();
  192. let position = _self._viewer.camera.position;
  193. let heading = _self._viewer.camera.heading;
  194. let pitch = _self._viewer.camera.pitch;
  195. let roll = _self._viewer.camera.roll;
  196. var pathsData = {
  197. "orientation": {
  198. "heading": heading,
  199. "pitch": pitch,
  200. "roll": roll
  201. },
  202. "position": position,
  203. "clampToGround": true, //开启贴地 如果有模型则贴模型
  204. "geometry": {
  205. "type": "LineString",
  206. "coordinates": coordinates
  207. }
  208. };
  209. _self._draw3DObj = pathsData;
  210. resolve(true);
  211. });
  212. },
  213. /**
  214. * 清空漫游路线
  215. */
  216. clearFlyPaths() {
  217. this._draw3DObj = null;
  218. this._viewer.trackedEntity = undefined;
  219. this._viewer.entities.remove(this.entityFly); //清空飞行路径模型
  220. },
  221. /**
  222. * 开始飞行
  223. */
  224. startFly(options,callError) {
  225. if (this._draw3DObj) {
  226. this._startFly(this._draw3DObj, options);
  227. } else {
  228. if (callError) callError('漫游路线不存在');
  229. }
  230. },
  231. /**
  232. * 暂停飞行
  233. */
  234. pauseFly() {
  235. var clockViewModel = this._viewer.clockViewModel;
  236. if (clockViewModel.shouldAnimate) {
  237. clockViewModel.shouldAnimate = false;
  238. } else if (this._viewer.clockViewModel.canAnimate) {
  239. clockViewModel.shouldAnimate = true;
  240. }
  241. },
  242. /**
  243. * 向前飞行
  244. */
  245. forwardFly() {
  246. var clockViewModel = this._viewer.clockViewModel;
  247. var multiplier = clockViewModel.multiplier;
  248. if (multiplier < 0) {
  249. clockViewModel.multiplier = -multiplier;
  250. }
  251. clockViewModel.shouldAnimate = true;
  252. },
  253. /**
  254. * 向后飞行
  255. */
  256. backwardsFly() {
  257. var clockViewModel = this._viewer.clockViewModel;
  258. var multiplier = clockViewModel.multiplier;
  259. if (multiplier > 0) {
  260. clockViewModel.multiplier = -multiplier;
  261. }
  262. clockViewModel.shouldAnimate = true;
  263. },
  264. /**
  265. * 退出飞行
  266. */
  267. outFly() {
  268. var start = Cesium.JulianDate.fromDate(new Date());
  269. this._viewer.clock.startTime = start.clone();
  270. var stop = Cesium.JulianDate.addSeconds(start, 300000000, new Cesium.JulianDate());
  271. this._viewer.clock.stopTime = stop.clone();
  272. this.clearFlyPaths();
  273. },
  274. });
  275. export default TrackRoam;