index.vue 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490
  1. <template>
  2. <div class="container">
  3. <div style="position: absolute;top: 20px;left: 20px;z-index: 9;">
  4. <div style="display: flex;">
  5. <el-select
  6. v-model="typeValue"
  7. placeholder="Select"
  8. style="width: 150px;background: black;"
  9. @change="changType"
  10. >
  11. <el-option
  12. v-for="item in options"
  13. :key="item.value"
  14. :label="item.label"
  15. :value="item.value"
  16. />
  17. </el-select>
  18. <el-input v-if="typeValue != 6" v-model="inputAddress" style="max-width: 200px;height: 32px;margin: 0px 10px;background: black;" placeholder="输入URL地址……" />
  19. <div style="padding: 0px 10px;" v-if="typeValue == 6">
  20. <el-upload
  21. ref="uploadRef"
  22. action=""
  23. :auto-upload="false"
  24. :file-list="fileList"
  25. :show-file-list="false"
  26. accept=".json,.geojson"
  27. :on-change="handleChange"
  28. >
  29. <template #trigger>
  30. <el-button type="primary">上传文件</el-button>
  31. </template>
  32. </el-upload>
  33. </div>
  34. <el-button type="primary" @click="parse">解析</el-button>
  35. </div>
  36. </div>
  37. <Map style="overflow: hidden;"></Map>
  38. <div class="infoDialog" v-show="infoDialogShow">
  39. <div class="close" @click="closeWin">×</div>
  40. <div class="content" v-if="nowPoint != null">
  41. <el-scrollbar>
  42. <div class="item" v-for="info in nowPointInfo" :key="info">{{info.key}}: {{ info.value }}</div>
  43. </el-scrollbar>
  44. </div>
  45. </div>
  46. </div>
  47. </template>
  48. <script>
  49. import { ElMessage } from 'element-plus'
  50. import Map from "@/views/example/Map.vue";
  51. import { toRaw } from "vue";
  52. export default {
  53. name: "",
  54. components: {
  55. Map
  56. },
  57. data() {
  58. return {
  59. listData:[],
  60. fileList: [],
  61. dataJson:[],
  62. wmslayer: {},
  63. pointImg:require('@static/images/point.png'),
  64. geometryArr:[],
  65. mapHandle:null,
  66. infoDialogShow:false,
  67. nowPoint: null,
  68. nowPointInfo:null,
  69. typeValue:'1',
  70. inputAddress:'http://121.43.55.7:8889/geoserver/kdyjs/wms',
  71. options:[
  72. {
  73. value: '1',
  74. label: '栅格WMS服务',
  75. },
  76. {
  77. value: '2',
  78. label: '栅格WMTS服务',
  79. },{
  80. value: '3',
  81. label: '栅格ArcGis服务',
  82. },
  83. {
  84. value: '4',
  85. label: '3dtiles数据',
  86. },
  87. // {
  88. // value: '5',
  89. // label: '矢量数据',
  90. // },
  91. {
  92. value: '6',
  93. label: '矢量文件',
  94. }
  95. ]
  96. };
  97. },
  98. mounted() {
  99. },
  100. methods: {
  101. beforeUpload(file) {
  102. const maxSize = 2; // 限制为2MB
  103. if (file.size / 1024 / 1024 > maxSize) {
  104. ElMessage({
  105. type: 'error',
  106. message: `文件大小不能超过 ${maxSize}MB!`,
  107. })
  108. return false;
  109. }
  110. return true;
  111. },
  112. handleChange(files,fileLists){
  113. let that = this;
  114. if (fileLists.length >1) {
  115. fileLists.shift();
  116. }
  117. that.fileList = fileLists;
  118. let reader = new FileReader();
  119. reader.readAsText(that.fileList[0].raw, "UTF-8");
  120. reader.onload = (evt) => {
  121. that.dataJson = JSON.parse(evt.target.result);
  122. console.log(that.dataJson); // 输出解析后的JSON数据
  123. ElMessage({
  124. type: 'success',
  125. message: `文件处理成功,请解析上图展示`,
  126. })
  127. };
  128. },
  129. closeWin() {
  130. this.infoDialogShow = false;
  131. this.nowPoint = null;
  132. this.nowPointInfo = null;
  133. },
  134. dwanMap(){
  135. let that = this;
  136. if(that.geometryArr.length>0){
  137. that.geometryArr.map(function (info) {
  138. viewer.entities.remove(info)
  139. })
  140. }
  141. that.geometryArr = that.dataJson.features.map(function (info) {
  142. if(info.geometry.type == "Point"){
  143. return that.addPoint(info)
  144. }else if(info.geometry.type == "LineString"){
  145. return that.addLine(info)
  146. }else{
  147. return that.addPolygon(info)
  148. }
  149. })
  150. that.pointTCHandle();
  151. },
  152. addPolygon(param){
  153. let arr = [];
  154. param.geometry.coordinates.forEach(element => {
  155. element.forEach(e => {
  156. arr.push(e[0]);
  157. arr.push(e[1]);
  158. })
  159. });
  160. return viewer.entities.add(new SkyScenery.Entity({
  161. name: " polygon",
  162. polygon: {
  163. hierarchy: {
  164. positions: SkyScenery.Cartesian3.fromDegreesArray(arr)
  165. },
  166. heightReference: SkyScenery.HeightReference.CLAMP_TO_GROUND,
  167. material: SkyScenery.Color.CYAN.withAlpha(0.5)
  168. },
  169. info: {
  170. coor: [arr[0], arr[1]],
  171. properties: param.properties
  172. },
  173. }));
  174. },
  175. addLine(param){
  176. return viewer.entities.add({
  177. name: "line",
  178. polyline: {
  179. //经纬度数组转世界坐标,带高度的话是fromDegreesArrayHeights
  180. positions: SkyScenery.Cartesian3.fromDegreesArray(param.geometry.coordinates),
  181. width: 2,
  182. material: SkyScenery.Color.CYAN,
  183. info: {
  184. properties: param.properties
  185. },
  186. }
  187. });
  188. },
  189. addPoint(param){
  190. let that = this;
  191. return viewer.entities.add(new SkyScenery.Entity({
  192. name:"point",
  193. position: SkyScenery.Cartesian3.fromDegrees(param.geometry.coordinates[0], param.geometry.coordinates[1]),
  194. type: "point",
  195. info: {
  196. coor: [param.geometry.coordinates[0], param.geometry.coordinates[1]],
  197. properties: param.properties
  198. },
  199. billboard: {
  200. image: that.pointImg,
  201. disableDepthTestDistance: Number.POSITIVE_INFINITY,
  202. scale: 0.3,
  203. horizontalOrigin: SkyScenery.HorizontalOrigin.CENTER,
  204. verticalOrigin: SkyScenery.VerticalOrigin.BOTTOM,
  205. }
  206. }));
  207. },
  208. // 点击事件绑定
  209. pointTCHandle() {
  210. let that = this;
  211. if (!this.mapHandle) {
  212. this.mapHandle = new SkyScenery.ScreenSpaceEventHandler(viewer.canvas, this);
  213. this.mapHandle.setInputAction(function (movement) {
  214. that.infoDialogShow = false
  215. const pickedObject = viewer.scene.pick(movement.position);
  216. let cartesian = viewer.camera.pickEllipsoid(
  217. movement.position,
  218. viewer.scene.globe.ellipsoid
  219. );
  220. // 空间坐标转世界坐标(弧度)
  221. let cartographic = SkyScenery.Cartographic.fromCartesian(cartesian);
  222. // 弧度转为角度(经纬度)
  223. let lon = SkyScenery.Math.toDegrees(cartographic.longitude); // 经度值
  224. let lat = SkyScenery.Math.toDegrees(cartographic.latitude); // 纬度值
  225. let center = [lon,lat]
  226. if (SkyScenery.defined(pickedObject) && SkyScenery.defined(pickedObject.id)) {
  227. const entity = pickedObject.id;
  228. that.infoDialogShow = true
  229. that.nowPoint = entity.info;
  230. that.nowPointInfo = Object.keys(that.nowPoint.properties).map(key => ({ key, value: that.nowPoint.properties[key] }));
  231. that.nowPoint["type"] = "info";
  232. // let xy = that.lonlatConvertToScreenXY(entity.info.coor)
  233. let xy = that.lonlatConvertToScreenXY(center)
  234. document.querySelector(".infoDialog").style.top = (xy.y - 230) + "px";
  235. document.querySelector(".infoDialog").style.left = (xy.x - 100) + "px";
  236. } else {
  237. // console.log('未拾取到实体');
  238. }
  239. }, SkyScenery.ScreenSpaceEventType.LEFT_CLICK);
  240. viewer.scene.postRender.addEventListener(that.updatePosition, this);
  241. } else {
  242. toRaw(this.mapHandle).destroy();
  243. this.mapHandle = null
  244. that.nowPointInfo = null
  245. viewer.scene.postRender.removeEventListener(that.updatePosition, this);
  246. }
  247. },
  248. // 经纬度转屏幕坐标
  249. lonlatConvertToScreenXY(lonlat) {
  250. // 定义经纬度
  251. var longitude = SkyScenery.Math.toRadians(lonlat[0]); // 例如:东经116.391度
  252. var latitude = SkyScenery.Math.toRadians(lonlat[1]); // 例如:北纬39.907度
  253. var height = 0; // 高度,通常在地表为0
  254. // 将经纬度转换为笛卡尔坐标
  255. // var cartographic = SkyScenery.Cartographic.fromDegrees(longitude, latitude, height);
  256. var cartesian = SkyScenery.Cartesian3.fromRadians(longitude, latitude, height, viewer.scene.globe.ellipsoid);
  257. // 将笛卡尔坐标转换为窗口坐标
  258. var canvasCoordinates = viewer.scene.cartesianToCanvasCoordinates(cartesian);
  259. return canvasCoordinates
  260. },
  261. // 位置更新
  262. updatePosition() {
  263. try {
  264. if (this.nowPoint != null) {
  265. const obj = toRaw(this.nowPoint);
  266. let xy = this.lonlatConvertToScreenXY(obj.coor)
  267. if (!xy) {
  268. document.querySelector(".infoDialog").style.top = "-9999px";
  269. document.querySelector(".infoDialog").style.left = "-9999px";
  270. } else {
  271. document.querySelector(".infoDialog").style.top = (xy.y - 230) + "px";
  272. document.querySelector(".infoDialog").style.left = (xy.x - 100) + "px";
  273. }
  274. }
  275. } catch (error) {
  276. // debugger
  277. }
  278. },
  279. addWMTSLayer(param) {
  280. let matrixIds = [];
  281. for (let i = 0; i < 19; i++) {
  282. matrixIds[i] = i + 1;
  283. }
  284. // this.removeMapLayer();
  285. // console.log('[ WMTS ] >'+param)
  286. let layer = viewer.imageryLayers.addImageryProvider(
  287. new SkyScenery.WebMapTileServiceImageryProvider({
  288. url: param.url,
  289. layer: param.layers, // 固定的 cia img vec cva 四种类型
  290. style: "default",
  291. format: "tiles",
  292. // format:"image/png",
  293. tileMatrixSetID: "w",
  294. TileMatrixLabels: matrixIds,
  295. subdomains: ["t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7"],
  296. minimumLevel: 1,
  297. maximumLevel: 18,
  298. tilingScheme: new SkyScenery.WebMercatorTilingScheme()
  299. })
  300. );
  301. this.wmslayer.mapItemLayer = layer;
  302. },
  303. addWMSLayer(param) {
  304. // console.log('[ WMS ] >'+param)
  305. let layer = viewer.imageryLayers.addImageryProvider(
  306. new SkyScenery.WebMapServiceImageryProvider({
  307. url: param.url,
  308. layers: param.layers, //固定的已发布的类型
  309. parameters: {
  310. TRANSPARENT: true,
  311. format: "image/png"
  312. }
  313. })
  314. );
  315. this.wmslayer.mapItemLayer = layer;
  316. },
  317. addARCGISLayer(param){
  318. // console.log('[ ArcGisMapServer ] >'+param)
  319. // this.removeMapLayer();
  320. // 添加地图服务
  321. let layer = viewer.imageryLayers.addImageryProvider(
  322. // 此处使用的地图服务地址也可存放在配置文件中
  323. new SkyScenery.ArcGisMapServerImageryProvider({
  324. url: param.url
  325. })
  326. );
  327. this.wmslayer.mapItemLayer = layer;
  328. },
  329. removeMapLayer(){
  330. // console.log('[ eee ] >')
  331. if(this.wmslayer.mapItemLayer){
  332. viewer.imageryLayers.remove(toRaw(this.wmslayer.mapItemLayer))
  333. delete this.wmslayer.mapItemLayer;
  334. }
  335. },
  336. getVectorData(param){
  337. let that = this;
  338. fetch(param.url, {
  339. method: 'GET',
  340. }).then(response => response.json()) // 假设服务器返回 JSON 数据
  341. .then(data => {
  342. console.log('[ eee ] >')
  343. that.dataJson = data.result;
  344. that.closeWin()
  345. that.dwanMap()
  346. })
  347. },
  348. add3dtilesData(param){
  349. console.log('[ add3dtilesData ] >'+param)
  350. let tile1 = new SkyScenery.add3DTilesData(param.url, viewer)
  351. tile1.readyPromise.then(function (tileset) {
  352. viewer.zoomTo(tile1)
  353. });
  354. },
  355. changType(){
  356. let that = this;
  357. // this.inputAddress = '';
  358. if(that.typeValue == 1){
  359. let curUrl = 'http://121.43.55.7:8889/geoserver/kdyjs/wms';
  360. that.inputAddress = curUrl;
  361. }else if(that.typeValue == 2){
  362. let type = "vec"; //cia img vec cva
  363. let curUrl = "https://{s}.tianditu.gov.cn/"+type+"_w/wmts?tk=f74e6c0cc247c42af05f7053e0b5fb9b";
  364. that.inputAddress = curUrl;
  365. }else if(that.typeValue == 3){
  366. let curUrl = 'https://service-api.onemap.sh.gov.cn/data-service-manage-service/MapProxyApi/eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhcHBsaWNhdGlvbl9pZCI6NjEsImFwcGxpY2F0aW9uX25hbWUiOiLpnZLmtabkuozkuInnu7TmnI3liqHns7vnu58iLCJleHAiOjIwNDY2Nzg0MDN9.IKUMdjUX4U1jncIUNren-iotL7duXI90aLECMjpvUX8/shmap_normal_web/MapServer';
  367. that.inputAddress = curUrl;
  368. }else if(that.typeValue == 4){
  369. let curUrl = "http://121.43.55.7:65456/shzx/tileset.json";
  370. that.inputAddress = curUrl;
  371. }else if(that.typeValue == 5){
  372. let curUrl = "http://121.43.55.7:10018/kdyjs/shop/recommend?type=1&size=20&banned=1,2,3";
  373. that.inputAddress = curUrl;
  374. }else if(that.typeValue == 6){
  375. that.inputAddress = "";
  376. }
  377. },
  378. parse(){
  379. let that = this;
  380. if( that.typeValue != 6 && that.inputAddress == ''){
  381. return ElMessage({
  382. type: 'error',
  383. message: `输入地址不能为空!请输入地址后进行解析`,
  384. })
  385. }
  386. console.log('[ eee ] >')
  387. // typeValue:'1',
  388. // inputAddress:'',
  389. if(that.typeValue == 1){
  390. // let curUrl = that.inputAddress;
  391. let curUrl = 'http://121.43.55.7:8889/geoserver/kdyjs/wms';
  392. that.inputAddress = curUrl;
  393. let param = {url:curUrl,layers:'kdyjs:CourtyardFace'}
  394. that.addWMSLayer(param)
  395. }else if(that.typeValue == 2){
  396. let type = "vec"; //cia img vec cva
  397. let curUrl = "https://{s}.tianditu.gov.cn/"+type+"_w/wmts?tk=f74e6c0cc247c42af05f7053e0b5fb9b";
  398. that.inputAddress = curUrl;
  399. let param = {url:curUrl,layers:type}
  400. that.addWMTSLayer(param)
  401. }else if(that.typeValue == 3){
  402. // let curUrl = that.inputAddress;
  403. let curUrl = 'https://service-api.onemap.sh.gov.cn/data-service-manage-service/MapProxyApi/eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhcHBsaWNhdGlvbl9pZCI6NjEsImFwcGxpY2F0aW9uX25hbWUiOiLpnZLmtabkuozkuInnu7TmnI3liqHns7vnu58iLCJleHAiOjIwNDY2Nzg0MDN9.IKUMdjUX4U1jncIUNren-iotL7duXI90aLECMjpvUX8/shmap_normal_web/MapServer';
  404. that.inputAddress = curUrl;
  405. let param = {url:curUrl,layers:'arcgisLayer'}
  406. that.addARCGISLayer(param)
  407. }else if(that.typeValue == 4){
  408. // let curUrl = that.inputAddress;
  409. let curUrl = "http://121.43.55.7:65456/shzx/tileset.json";
  410. that.inputAddress = curUrl;
  411. let param = {url:curUrl}
  412. that.add3dtilesData(param);
  413. }else if(that.typeValue == 5){
  414. // let curUrl = that.inputAddress;
  415. let curUrl = "https://kdyjs-proxy.metamaker.cn/proxy_map/static/json/%E6%A5%BC%E5%AE%87%E6%95%B0%E6%8D%AE-20250820.geojson";
  416. that.inputAddress = curUrl;
  417. let param = {url:curUrl}
  418. that.getVectorData(param);
  419. }else if(that.typeValue == 6){
  420. //上传GeoJson文件解析数据并上图
  421. if(this.mapHandle){
  422. toRaw(this.mapHandle).destroy();
  423. this.mapHandle = null
  424. that.nowPointInfo = null
  425. }
  426. that.closeWin()
  427. that.dwanMap()
  428. }
  429. }
  430. },
  431. beforeDestroy() {
  432. viewer = undefined
  433. }
  434. };
  435. </script>
  436. <style lang="less" scoped>
  437. .container {
  438. width: 100%;
  439. padding: 0px;
  440. margin: 0 auto;
  441. overflow: hidden;
  442. }
  443. .infoDialog {
  444. position: absolute;
  445. top: 0px;
  446. left: 0px;
  447. max-width: 500px;
  448. height: 200px;
  449. // background: #01346f99;
  450. background: #ffffff;
  451. border-radius: 10px;
  452. .close {
  453. font-size: 24px;
  454. position: absolute;
  455. top: 6px;
  456. right: 8px;
  457. line-height: 24px;
  458. width: 24px;
  459. height: 24px;
  460. cursor: pointer;
  461. // color: #ffffff;
  462. color: #000000;
  463. }
  464. .content {
  465. height: 160px;
  466. // color: #ffffff;
  467. color: #000000;
  468. margin: 30px 0px 10px 20px;
  469. overflow: auto;
  470. .item {
  471. line-height: 30px;
  472. margin-right: 20px;
  473. }
  474. }
  475. }
  476. </style>