locateUtil.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303
  1. /* 引入Cesium */
  2. // import * as Cesium from 'Cesium';
  3. /**
  4. * Cesium 的各种定位方法汇总,只列出项目中经常使用的,如果不够灵活,可直接调用Cesium官方API,也很方便。
  5. * Cesium的定位从效果上包含两种:直接定位、飞行定位。在方法封装上,姑且将直接定位分类为zoomTo系列,飞行定位分类flyTo。
  6. * 定位的对象上包括:坐标点、矩形范围、entities、3dtiles、gltf、kml、geojson、影像、地形、geometry
  7. * Cesium的定位主要是使用Camera对象和Viewer对象,Viewer的定位zoomTo,flyTo等方法是较高级别的函数,可以定位到Entity、3dtiles、DataSource等添加到三维球上显示的实体,
  8. * Viewer的定位方法内部都是调用Camera的相关定位方法,针对不同的定位对象,通过一些列计算得出传入实体的合适定位范围和摄像机视角,然后定位,使用起来很方便。
  9. * Camera的flyTo、flyToBoundingSphere、lookat、setView等方法是较低级别函数,通过定位坐标和角度参数的传入,精细化控制定位视角,灵活。
  10. */
  11. class LocateUtil {
  12. /**
  13. * 默认初始化
  14. * @param {Object} viewer 三维场景
  15. */
  16. constructor(viewer) {
  17. if (!viewer) throw new Cesium.DeveloperError('no viewer object!');
  18. this._viewer = viewer;
  19. this._locationEntity = null;
  20. }
  21. }
  22. /**
  23. * 通用对外公开函数(坐标定位)
  24. */
  25. Object.assign(LocateUtil.prototype, /** @lends LocateUtil.prototype */ {
  26. /**
  27. * 飞行定位到一个笛卡尔空间直角坐标点位置
  28. * @param {Object} options 具有以下属性:
  29. * @param {Number} options.longitude 经度,以度为单位
  30. * @param {Number} options.latitude 纬度,以度为单位
  31. * @param {Number} [options.height=0.0] 椭球的高度,以米为单位
  32. * @param {Number} [options.heading=0.0] 指向,默认值0.0(北)
  33. * @param {Number} [options.pitch=-90] 俯仰角, 垂直向下。默认值-90(向下看)。俯仰,人如果在赤道上空,俯仰角为0可见地球。如果在北纬,俯仰角为负才能见地球
  34. * @param {Number} [options.range=0.0] 距目标点距离
  35. * @param {Number} [options.duration=3] 持续时间
  36. */
  37. flyToPoint: function(options) {
  38. return new Promise((resolve, reject) => {
  39. if (!Cesium.defined(options) || !Cesium.defined(options.longitude) || !Cesium.defined(options.latitude)) {
  40. throw new Cesium.DeveloperError("options.longitude and options.latitude are required.");
  41. }
  42. // 初始化参数默认值
  43. options.height = Cesium.defaultValue(options.height, 0);
  44. options.heading = Cesium.defaultValue(options.heading, 0);
  45. options.pitch = Cesium.defaultValue(options.pitch, -90);
  46. options.range = Cesium.defaultValue(options.range, 0.0);
  47. options.duration = Cesium.defaultValue(options.duration, 3);
  48. var boundingSphere = new Cesium.BoundingSphere(Cesium.Cartesian3.fromDegrees(options.longitude, options.latitude, options.height), 0.0);
  49. this._viewer.camera.flyToBoundingSphere(boundingSphere, {
  50. duration: options.duration,
  51. complete: function() {
  52. resolve(true);
  53. },
  54. offset: {
  55. heading: Cesium.Math.toRadians(options.heading),
  56. pitch: Cesium.Math.toRadians(options.pitch),
  57. range: options.range
  58. },
  59. });
  60. });
  61. },
  62. /**
  63. * @description 根据坐标飞行定位,支持点、线、面等
  64. * @param {Array} points 坐标集合 [[lng,lat],[lng,lat],......]
  65. * @param {String} type 定位类型 point multiplePoint polyline polygon
  66. * @param {Object} [options] 飞行的样式,具有以下属性:
  67. * @param {Number} [options.heading=0.0] 指向,默认值0.0(北)
  68. * @param {Number} [options.pitch=-90] 俯仰角, 垂直向下。默认值-90(向下看)。俯仰,人如果在赤道上空,俯仰角为0可见地球。如果在北纬,俯仰角为负才能见地球
  69. * @param {Number} [options.range=0.0] 距目标点距离
  70. * @param {Number} [options.duration=3] 持续时间
  71. */
  72. flyToEntityByPoints: function(points, type, options) {
  73. return new Promise((resolve, reject) => {
  74. let _self = this;
  75. options = options || {};
  76. if (points === undefined || points.length === undefined) {
  77. reject("输入的坐标集合异常!");
  78. return;
  79. }
  80. /* 转换坐标 */
  81. let pointsArray = points.map(point => {
  82. return Cesium.Cartesian3.fromDegrees(point[0], point[1], point[2] || 0);
  83. });
  84. if (_self._locationEntity) {
  85. _self._viewer.entities.remove(_self._locationEntity);
  86. }
  87. /* 分别判断 */
  88. switch (type) {
  89. case "point":
  90. _self._locationEntity = _self._viewer.entities.add({
  91. position: pointsArray[0],
  92. point: {
  93. pixelSize: 1,
  94. },
  95. });
  96. break;
  97. case "polyline":
  98. if (pointsArray.length < 2) {
  99. reject("线对象定位,点数至少2个");
  100. } else {
  101. _self._locationEntity = _self._viewer.entities.add({
  102. polyline: {
  103. positions: pointsArray,
  104. clampToGround: true, //指定折线是否应该固定在地面上
  105. // material: new Cesium.Color.fromCssColorString("#ffffff00"),
  106. material: new Cesium.Color(255, 0, 0, 0.5),
  107. width: 1,
  108. }
  109. });
  110. }
  111. break;
  112. case "polygon":
  113. if (pointsArray.length < 3) {
  114. reject("面对象定位,点数至少3个");
  115. } else {
  116. _self._locationEntity = _self._viewer.entities.add({
  117. polygon: {
  118. hierarchy: {
  119. positions: pointsArray
  120. },
  121. // material: new Cesium.Color.fromCssColorString("#ffffff00"),
  122. material: new Cesium.Color(255, 0, 0, 0.5),
  123. outline: true,
  124. }
  125. });
  126. }
  127. break;
  128. default:
  129. reject("坐标异常!");
  130. break;
  131. }
  132. // 初始化参数默认值
  133. options.duration = Cesium.defaultValue(options.duration, 3);
  134. options.heading = Cesium.defaultValue(options.heading, 0);
  135. options.pitch = Cesium.defaultValue(options.pitch, -90);
  136. options.range = Cesium.defaultValue(options.range, 0.0);
  137. let flyPromise = _self._viewer.flyTo(_self._locationEntity, {
  138. duration: options.duration,
  139. offset: {
  140. heading: Cesium.Math.toRadians(options.heading),
  141. pitch: Cesium.Math.toRadians(options.pitch),
  142. range: options.range
  143. }
  144. });
  145. flyPromise.then(function(flag) {
  146. if (flag) {
  147. // _self._viewer.entities.remove(_self._locationEntity);
  148. resolve(_self._locationEntity);
  149. }
  150. });
  151. });
  152. },
  153. /**
  154. * @description 飞行定位到一个实体
  155. * @param {Object} entity
  156. * @param {Number} [options.heading=0.0] 指向,默认值0.0(北)
  157. * @param {Number} [options.pitch=-90] 俯仰角, 垂直向下。默认值-90(向下看)。俯仰,人如果在赤道上空,俯仰角为0可见地球。如果在北纬,俯仰角为负才能见地球
  158. * @param {Number} [options.range=0.0] 距目标点距离
  159. * @param {Number} [options.duration=3] 持续时间
  160. */
  161. flyToEntity: function(entity, options) {
  162. return new Promise((resolve, reject) => {
  163. let _self = this;
  164. options = options || {};
  165. if (_self._locationEntity) {
  166. _self._viewer.entities.remove(_self._locationEntity);
  167. }
  168. _self._locationEntity = entity;
  169. // 初始化参数默认值
  170. options.duration = Cesium.defaultValue(options.duration, 3);
  171. options.heading = Cesium.defaultValue(options.heading, 0);
  172. options.pitch = Cesium.defaultValue(options.pitch, -90);
  173. options.range = Cesium.defaultValue(options.range, 0.0);
  174. let flyPromise = _self._viewer.flyTo(_self._locationEntity, {
  175. duration: options.duration,
  176. offset: {
  177. heading: Cesium.Math.toRadians(options.heading),
  178. pitch: Cesium.Math.toRadians(options.pitch),
  179. range: options.range
  180. }
  181. });
  182. flyPromise.then(function(flag) {
  183. if (flag) {
  184. // _self._viewer.entities.remove(_self._locationEntity);
  185. resolve(_self._locationEntity);
  186. }
  187. });
  188. });
  189. },
  190. /**
  191. * 定位实景三维
  192. * @param {Object} tileset
  193. * @param {Object} [options] 飞行的样式,具有以下属性:
  194. * @param {Number} [options.heading=120] 指向,默认值0.0(北)
  195. * @param {Number} [options.pitch=-10] 俯仰角, 垂直向下。默认值-90(向下看)。俯仰,人如果在赤道上空,俯仰角为0可见地球。如果在北纬,俯仰角为负才能见地球
  196. * @param {Number} [options.range=450.0] 距目标点距离
  197. * @param {Number} [options.duration=3] 持续时间
  198. */
  199. zoomToTilesets(tileset, options) {
  200. return new Promise((resolve, reject) => {
  201. let _self = this;
  202. if (!Cesium.defined(tileset)) {
  203. throw new Cesium.DeveloperError("tileset is required.");
  204. }
  205. // 初始化参数默认值
  206. options = options || {};
  207. options.heading = Cesium.defaultValue(options.heading, 120);
  208. options.pitch = Cesium.defaultValue(options.pitch, -10);
  209. options.range = Cesium.defaultValue(options.range, 450.0);
  210. options.duration = Cesium.defaultValue(options.duration, 3);
  211. // var boundingSphere = new Cesium.BoundingSphere(Cesium.Cartesian3.fromDegrees(options.longitude, options.latitude, options.height), 0.0);
  212. let boundingSphere = tileset.boundingSphere;
  213. _self._viewer.camera.flyToBoundingSphere(boundingSphere, {
  214. duration: options.duration,
  215. complete: function() {
  216. resolve(true);
  217. },
  218. offset: {
  219. heading: Cesium.Math.toRadians(options.heading),
  220. pitch: Cesium.Math.toRadians(options.pitch),
  221. range: options.range
  222. },
  223. });
  224. });
  225. },
  226. /**
  227. * 飞行定位实景三维
  228. * @param {Object} tileset
  229. * @param {Object} [options] 飞行的样式,具有以下属性:
  230. * @param {Number} [options.heading=120] 指向,默认值0.0(北)
  231. * @param {Number} [options.pitch=-10] 俯仰角, 垂直向下。默认值-90(向下看)。俯仰,人如果在赤道上空,俯仰角为0可见地球。如果在北纬,俯仰角为负才能见地球
  232. * @param {Number} [options.range=450.0] 距目标点距离
  233. * @param {Number} [options.duration=3] 持续时间
  234. */
  235. flyToTileset(tileset, options) {
  236. return new Promise((resolve, reject) => {
  237. let _self = this;
  238. if (!Cesium.defined(tileset)) {
  239. throw new Cesium.DeveloperError("tileset is required.");
  240. }
  241. // 初始化参数默认值
  242. options = options || {};
  243. options.heading = Cesium.defaultValue(options.heading, 120);
  244. options.pitch = Cesium.defaultValue(options.pitch, -10);
  245. options.range = Cesium.defaultValue(options.range, 450.0);
  246. options.duration = Cesium.defaultValue(options.duration, 3);
  247. /*viewer.flyTo() 方法,返回一个 promise (承诺)。
  248. * 如果飞行成功,该承诺将解析为 true;
  249. * 如果视图中目标不可见或飞行被取消,该承诺将解析为 false。
  250. * 用途:在飞到某实体后,移除该实体。*/
  251. let flyPromise = _self._viewer.flyTo(tileset, {
  252. duration: options.duration,
  253. offset: {
  254. heading: Cesium.Math.toRadians(options.heading),
  255. pitch: Cesium.Math.toRadians(options.pitch),
  256. range: options.range
  257. }
  258. });
  259. flyPromise.then(function(flag) {
  260. if (flag) {
  261. resolve(true);
  262. }
  263. });
  264. });
  265. }
  266. });
  267. export default LocateUtil;