├── src ├── mock │ ├── qianxitu │ │ └── hzSolid.json │ ├── line │ │ ├── stationList1.json │ │ └── geoJsonline.json │ ├── polygon │ │ └── mockPolygon.json │ └── popUp │ │ └── stationList1.json ├── map │ ├── service │ │ ├── mapbox │ │ │ ├── imageryProvider │ │ │ │ └── index.ts │ │ │ └── pugin │ │ │ │ └── echartslayer-libs │ │ │ │ ├── README.MD │ │ │ │ ├── index.js │ │ │ │ ├── lib │ │ │ │ ├── GLMapModel.js │ │ │ │ ├── GLMap.js │ │ │ │ ├── EchartsLayer.js │ │ │ │ ├── GLMapCoordSys.js │ │ │ │ └── GLMapView.js │ │ │ │ └── dist │ │ │ │ └── EchartsLayer.min.js │ │ ├── cesium │ │ │ ├── plugin │ │ │ │ ├── README.MD │ │ │ │ └── echarts │ │ │ │ │ ├── RegisterCoordinateSystem.ts │ │ │ │ │ └── EchartsLayer.ts │ │ │ ├── imageryProvider │ │ │ │ ├── index.ts │ │ │ │ ├── tdt │ │ │ │ │ └── TdtImageryProvider.ts │ │ │ │ ├── amap │ │ │ │ │ ├── AmapImageryProvider.ts │ │ │ │ │ └── AmapMercatorTilingScheme.ts │ │ │ │ └── baidu │ │ │ │ │ ├── BaiduMercatorTilingScheme.ts │ │ │ │ │ └── BaiduImageryProvider.ts │ │ │ └── widgets │ │ │ │ ├── CesiumCustomPopUp.ts │ │ │ │ └── CesiumClusterWidgets.ts │ │ ├── leaflet │ │ │ ├── pugin │ │ │ │ └── README.MD │ │ │ ├── load │ │ │ │ └── index.ts │ │ │ ├── markerCluster │ │ │ │ └── LeafletMarkerCluster.ts │ │ │ └── imageryProvider │ │ │ │ ├── TileLayerBaidu.ts │ │ │ │ └── index.ts │ │ ├── LeafletService.ts │ │ └── CesiumService.ts │ ├── type │ │ ├── MapBoxType.ts │ │ ├── LeafletType.ts │ │ ├── CesiumType.ts │ │ └── CommonType.ts │ ├── common │ │ ├── MapService.ts │ │ ├── pugin │ │ │ └── echartslayer-libs │ │ │ │ ├── index.js │ │ │ │ ├── lib │ │ │ │ ├── GLMapModel.js │ │ │ │ ├── GLMap.js │ │ │ │ ├── EchartsLayer.js │ │ │ │ ├── GLMapCoordSys.js │ │ │ │ └── GLMapView.js │ │ │ │ └── dist │ │ │ │ └── EchartsLayer.min.js │ │ └── CommonStore.ts │ └── utils │ │ └── CoordTransform.ts ├── style │ ├── index.css │ └── main.css ├── assets │ └── map │ │ ├── site-5.png │ │ └── site.png ├── utils │ └── hintMessage.ts ├── components │ ├── dialog │ │ ├── migrationMap │ │ │ ├── MigrationMapDialogInstance.ts │ │ │ └── MigrationMapDialog.vue │ │ ├── popUp │ │ │ ├── commonWidget │ │ │ │ └── VuePointDetailComponent.vue │ │ │ ├── CesiumPopUpDialog.vue │ │ │ ├── MapboxPopUpDialog.vue │ │ │ └── LeafletPopUpDialog.vue │ │ ├── marker │ │ │ ├── LeafletMarkerDialog.vue │ │ │ ├── MapboxMarkerDialog.vue │ │ │ └── CesiumMarkerDialog.vue │ │ ├── cover │ │ │ ├── MapboxCoverDialog.vue │ │ │ ├── CesiumCoverDialog.vue │ │ │ └── LeafletCoverDialog.vue │ │ ├── line │ │ │ ├── CesiumLineDialog.vue │ │ │ ├── LeafletLineDialog.vue │ │ │ └── MapboxLineDialog.vue │ │ └── interpolation │ │ │ └── InterpolationDialog.vue │ ├── layouts │ │ ├── BaseLayout.vue │ │ └── SettingLayout.vue │ ├── controlWidget │ │ ├── LayerControlWidget.vue │ │ └── CommonIconDialog.vue │ ├── mini │ │ └── HelloWorldComponent.vue │ ├── aside │ │ ├── SlideTree.vue │ │ └── Index.vue │ └── Map │ │ ├── MapBoxView.vue │ │ ├── LeafletView.vue │ │ └── CesiumView.vue ├── views │ ├── about │ │ └── AboutList.vue │ ├── dataManage │ │ └── WindFieldPage.vue │ ├── modelManage │ │ ├── CesiumCityModel.vue │ │ ├── MapBoxBaseModel.vue │ │ ├── MapBoxCityModel.vue │ │ └── CesiumBaseModel.vue │ ├── pug │ │ └── Pug.vue │ ├── home │ │ └── HomeList.vue │ └── Main.vue ├── store │ ├── index.ts │ └── module │ │ └── app.ts ├── shims-tsx.d.ts ├── main.ts ├── shims-vue.d.ts ├── puglin │ └── LoadingPluginService.ts ├── data │ └── gltf │ │ ├── rectangle.gltf │ │ ├── house.gltf │ │ └── pyramid.gltf ├── router │ └── index.ts └── directives │ └── draggable.js ├── .eslintignore ├── .prettierrc ├── postcss.config.js ├── Dockerfile ├── .editorconfig ├── k8s ├── service.yml ├── ingress.yml └── deployment.yml ├── .gitignore ├── readme.md ├── .babelrc ├── tsconfig.build.json ├── tsconfig.json ├── public ├── index.html └── static │ └── kriging.min.js ├── .eslintrc └── package.json /src/mock/qianxitu/hzSolid.json: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | build/** 2 | dist/** 3 | -------------------------------------------------------------------------------- /src/map/service/mapbox/imageryProvider/index.ts: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/style/index.css: -------------------------------------------------------------------------------- 1 | @import "./main.css"; 2 | -------------------------------------------------------------------------------- /src/map/service/cesium/plugin/README.MD: -------------------------------------------------------------------------------- 1 | ## cesium 插件 2 | -------------------------------------------------------------------------------- /src/map/service/leaflet/pugin/README.MD: -------------------------------------------------------------------------------- 1 | ## leaflet echarts 图层插件 2 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true, 3 | "trailingComma": "all" 4 | } -------------------------------------------------------------------------------- /src/map/service/mapbox/pugin/echartslayer-libs/README.MD: -------------------------------------------------------------------------------- 1 | ## MAPBOX echarts 图层插件 2 | -------------------------------------------------------------------------------- /postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: [ 3 | require('autoprefixer') 4 | ] 5 | }; 6 | -------------------------------------------------------------------------------- /src/assets/map/site-5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/canyuegongzi/simple-gis-web/HEAD/src/assets/map/site-5.png -------------------------------------------------------------------------------- /src/assets/map/site.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/canyuegongzi/simple-gis-web/HEAD/src/assets/map/site.png -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM nginx:1.15.0 2 | MAINTAINER canyuegongzi 3 | EXPOSE 8045 4 | COPY ./dist /usr/share/nginx/html/simple-gis-web/ 5 | -------------------------------------------------------------------------------- /src/utils/hintMessage.ts: -------------------------------------------------------------------------------- 1 | export function hintMessage(message: string) { 2 | // TODO 根据业务逻辑处理提示 3 | alert(message); 4 | } 5 | -------------------------------------------------------------------------------- /src/map/type/MapBoxType.ts: -------------------------------------------------------------------------------- 1 | import { MapboxOptions } from 'mapbox-gl'; 2 | 3 | export interface MapBoxInstanceOptions { 4 | id: string; 5 | [key:string]: any 6 | } 7 | -------------------------------------------------------------------------------- /src/components/dialog/migrationMap/MigrationMapDialogInstance.ts: -------------------------------------------------------------------------------- 1 | export type MigrationMapDialogDataTypeInstance = 'SOLID' 2 | export type MigrationMapDialogSkillTypeInstance = 'ECHARTS' 3 | -------------------------------------------------------------------------------- /src/map/type/LeafletType.ts: -------------------------------------------------------------------------------- 1 | import { MapOptions } from 'leaflet'; 2 | 3 | export interface LeafletInstanceOptions extends MapOptions{ 4 | id: string; 5 | [key: string]: any 6 | } 7 | -------------------------------------------------------------------------------- /src/map/common/MapService.ts: -------------------------------------------------------------------------------- 1 | import { MapInitOptions, MapTypeEnum } from '@/map/type/CommonType'; 2 | 3 | export default class MapService { 4 | public mapInstanceMap: Record; 5 | 6 | } 7 | -------------------------------------------------------------------------------- /src/map/common/pugin/echartslayer-libs/index.js: -------------------------------------------------------------------------------- 1 | // @ts-ignore 2 | require("./lib/GLMap.js"); 3 | // @ts-ignore 4 | var EchartsLayer = require("./lib/EchartsLayer.js"); 5 | module.exports = EchartsLayer; 6 | -------------------------------------------------------------------------------- /src/map/service/mapbox/pugin/echartslayer-libs/index.js: -------------------------------------------------------------------------------- 1 | // @ts-ignore 2 | require("./lib/GLMap.js"); 3 | // @ts-ignore 4 | var EchartsLayer = require("./lib/EchartsLayer.js"); 5 | module.exports = EchartsLayer; 6 | -------------------------------------------------------------------------------- /src/map/service/leaflet/load/index.ts: -------------------------------------------------------------------------------- 1 | import L from 'leaflet'; 2 | import 'leaflet/dist/leaflet.css'; 3 | // 加载 supermap 4 | import '@supermap/iclient-leaflet'; 5 | 6 | /** 7 | * 将 L 挂载在 window 上 8 | */ 9 | window.L = L; 10 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = space 5 | indent_size = 4 6 | end_of_line = lf 7 | charset = utf-8 8 | trim_trailing_whitespace = true 9 | insert_final_newline = true 10 | 11 | [*.md] 12 | trim_trailing_whitespace = false 13 | -------------------------------------------------------------------------------- /src/views/about/AboutList.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 13 | 14 | 17 | -------------------------------------------------------------------------------- /src/map/service/cesium/imageryProvider/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * 注册图层 3 | */ 4 | import AmapImageryProvider from './amap/AmapImageryProvider'; 5 | import BaiduImageryProvider from './baidu/BaiduImageryProvider'; 6 | import TdtImageryProvider from './tdt/TdtImageryProvider'; 7 | 8 | export { AmapImageryProvider, BaiduImageryProvider, TdtImageryProvider }; 9 | -------------------------------------------------------------------------------- /src/store/index.ts: -------------------------------------------------------------------------------- 1 | import Vue from 'vue'; 2 | import Vuex, { Store } from 'vuex'; 3 | import APPModule from './module/app'; 4 | 5 | Vue.use(Vuex); 6 | export default new Vuex.Store({ 7 | // plugins, 8 | modules: { 9 | 'appModule': APPModule 10 | }, 11 | state: {}, 12 | mutations: {}, 13 | actions: {} 14 | 15 | }); 16 | -------------------------------------------------------------------------------- /src/shims-tsx.d.ts: -------------------------------------------------------------------------------- 1 | import Vue, { VNode } from 'vue'; 2 | 3 | declare global { 4 | namespace JSX { 5 | // tslint:disable no-empty-interface 6 | interface Element extends VNode {} 7 | // tslint:disable no-empty-interface 8 | interface ElementClass extends Vue {} 9 | interface IntrinsicElements { 10 | [elem: string]: any; 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /k8s/service.yml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | labels: 5 | app: simple-gis-web 6 | name: simple-gis-web-service 7 | spec: 8 | type: LoadBalancer 9 | ports: 10 | - name: simple-gis-web-port 11 | port: 8045 12 | protocol: TCP 13 | targetPort: 80 14 | selector: 15 | app: simple-gis-web 16 | -------------------------------------------------------------------------------- /src/map/common/pugin/echartslayer-libs/lib/GLMapModel.js: -------------------------------------------------------------------------------- 1 | define(function (require) { 2 | 3 | return require('echarts').extendComponentModel({ 4 | type: 'GLMap', 5 | 6 | getBMap: function () { 7 | // __bmap is injected when creating BMapCoordSys 8 | return this.__GLMap; 9 | }, 10 | 11 | defaultOption: { 12 | roam: false 13 | } 14 | }); 15 | }); -------------------------------------------------------------------------------- /src/map/service/mapbox/pugin/echartslayer-libs/lib/GLMapModel.js: -------------------------------------------------------------------------------- 1 | define(function (require) { 2 | 3 | return require('echarts').extendComponentModel({ 4 | type: 'GLMap', 5 | 6 | getBMap: function () { 7 | // __bmap is injected when creating BMapCoordSys 8 | return this.__GLMap; 9 | }, 10 | 11 | defaultOption: { 12 | roam: false 13 | } 14 | }); 15 | }); -------------------------------------------------------------------------------- /src/views/dataManage/WindFieldPage.vue: -------------------------------------------------------------------------------- 1 | 5 | 6 | 13 | 14 | 21 | -------------------------------------------------------------------------------- /src/views/modelManage/CesiumCityModel.vue: -------------------------------------------------------------------------------- 1 | 5 | 6 | 13 | 14 | 21 | -------------------------------------------------------------------------------- /src/views/modelManage/MapBoxBaseModel.vue: -------------------------------------------------------------------------------- 1 | 5 | 6 | 13 | 14 | 21 | -------------------------------------------------------------------------------- /src/views/modelManage/MapBoxCityModel.vue: -------------------------------------------------------------------------------- 1 | 5 | 6 | 13 | 14 | 21 | -------------------------------------------------------------------------------- /k8s/ingress.yml: -------------------------------------------------------------------------------- 1 | apiVersion: extensions/v1beta1 2 | kind: Ingress 3 | metadata: 4 | name: simple-gis-web-ingress 5 | namespace: default 6 | annotations: 7 | kubernetes.io/ingress.class: traefik 8 | spec: 9 | rules: 10 | - http: 11 | paths: 12 | - path: /simple-gis-web 13 | pathType: Prefix 14 | backend: 15 | serviceName: simple-gis-web-service 16 | servicePort: 8045 17 | -------------------------------------------------------------------------------- /src/main.ts: -------------------------------------------------------------------------------- 1 | import Vue from 'vue'; 2 | import Main from './views/Main.vue'; 3 | import store from './store'; 4 | import './style/index.css'; 5 | import { router } from "./router"; 6 | import ElementUI from 'element-ui'; 7 | import echarts from 'echarts'; 8 | Vue.use(ElementUI); 9 | import 'element-ui/lib/theme-chalk/index.css'; 10 | import './directives/draggable.js'; 11 | (window as any).echarts = echarts; 12 | Vue.config.productionTip = false; 13 | 14 | new Vue({ 15 | router, 16 | store, 17 | render: h => h(Main), 18 | }).$mount('#root'); 19 | -------------------------------------------------------------------------------- /src/map/common/pugin/echartslayer-libs/lib/GLMap.js: -------------------------------------------------------------------------------- 1 | /** 2 | * GLMap component extension 3 | */ 4 | define(function (require) { 5 | require('echarts').registerCoordinateSystem( 6 | 'GLMap', require('./GLMapCoordSys') 7 | ) 8 | require('./GLMapModel') 9 | require('./GLMapView') 10 | 11 | // Action 12 | require('echarts').registerAction({ 13 | type: 'GLMapRoam', 14 | event: 'GLMapRoam', 15 | update: 'updateLayout' 16 | }, function (payload, ecModel) {}) 17 | 18 | return { 19 | version: '1.0.0' 20 | } 21 | }) 22 | 23 | 24 | -------------------------------------------------------------------------------- /src/map/service/mapbox/pugin/echartslayer-libs/lib/GLMap.js: -------------------------------------------------------------------------------- 1 | /** 2 | * GLMap component extension 3 | */ 4 | define(function (require) { 5 | require('echarts').registerCoordinateSystem( 6 | 'GLMap', require('./GLMapCoordSys') 7 | ) 8 | require('./GLMapModel') 9 | require('./GLMapView') 10 | 11 | // Action 12 | require('echarts').registerAction({ 13 | type: 'GLMapRoam', 14 | event: 'GLMapRoam', 15 | update: 'updateLayout' 16 | }, function (payload, ecModel) {}) 17 | 18 | return { 19 | version: '1.0.0' 20 | } 21 | }) 22 | 23 | 24 | -------------------------------------------------------------------------------- /k8s/deployment.yml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | labels: 5 | app: simple-gis-web 6 | name: simple-gis-web 7 | spec: 8 | replicas: 1 9 | selector: 10 | matchLabels: 11 | app: simple-gis-web 12 | template: 13 | metadata: 14 | labels: 15 | app: simple-gis-web 16 | spec: 17 | containers: 18 | - image: canyuegongzi/simple-gis-web:2.5 19 | imagePullPolicy: IfNotPresent 20 | name: simple-gis-web 21 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # compiled output 2 | /dist 3 | /node_modules 4 | /war 5 | 6 | # Logs 7 | logs 8 | *.log 9 | npm-debug.log* 10 | yarn-debug.log* 11 | yarn-error.log* 12 | lerna-debug.log* 13 | package-lock.json 14 | .idea 15 | war 16 | # OS 17 | .DS_Store 18 | 19 | # Tests 20 | /coverage 21 | /.nyc_output 22 | 23 | # IDEs and editors 24 | /.idea 25 | .project 26 | .classpath 27 | .c9/ 28 | *.launch 29 | .settings/ 30 | *.sublime-workspace 31 | 32 | # IDE - VSCode 33 | .vscode/* 34 | !.vscode/settings.json 35 | !.vscode/tasks.json 36 | !.vscode/launch.json 37 | !.vscode/extensions.json 38 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | ## simple-gis-web 2 | 3 | leaflet,mapbox,cesium 通用业务功能封装,框架布局以vue为基础,但地图相关的基础功能已经单独抽离为Service,可单独使用 4 | 5 | 此案例基于笔者近一年多的 webGis 开发经验整理完成,包括常见的点、 线、面、弹框、数据可视化、差值渲染等,后续会抽时间逐步更新。 6 | 7 | 1. [前端开发中如何实现WebGIS数据可视化(一)——地图创建、点位绘制](https://juejin.cn/post/6985900607588532260) 8 | 2. [前端开发中如何实现WebGIS数据可视化(二)——线、面绘制](https://juejin.cn/post/6988758381225836552) 9 | 3. [前端开发中如何实现WebGIS数据可视化(三)——迁徙图绘制](https://juejin.cn/post/6988758381225836552) 10 | 11 | ```bin 12 | docker build -t simple-gis-web . 13 | 14 | docker tag 713f3970cee9b1734546b88a7ccf61c14947236686d9ba85f990200e5781b32a canyuegongzi/simple-gis-web:1.2 15 | 16 | docker push canyuegongzi/simple-gis-web:1.3 17 | 18 | ``` 19 | -------------------------------------------------------------------------------- /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | [ 4 | "@babel/preset-env", 5 | { 6 | "useBuiltIns": false 7 | } 8 | ], 9 | [ 10 | "@babel/preset-typescript", 11 | { 12 | "allExtensions": true 13 | } 14 | ] 15 | ], 16 | "plugins": [ 17 | [ 18 | "@babel/plugin-proposal-decorators", 19 | { 20 | "legacy": true 21 | } 22 | ], 23 | [ 24 | "@babel/plugin-proposal-class-properties" 25 | ], 26 | [ 27 | "@babel/plugin-transform-runtime" 28 | ] 29 | ] 30 | } 31 | -------------------------------------------------------------------------------- /src/map/common/CommonStore.ts: -------------------------------------------------------------------------------- 1 | import { MapTypeEnum } from '../type/CommonType'; 2 | 3 | class CommonStore { 4 | public mapInstanceMap: Map = new Map(); 5 | /** 6 | * 读取地图实例 7 | * @param type 8 | * @protected 9 | */ 10 | public async getInstance(type: MapTypeEnum) { 11 | if (this.mapInstanceMap.get(type)) { 12 | return this.mapInstanceMap.get(type); 13 | } 14 | } 15 | 16 | /** 17 | * 保存地图实例 18 | * @param type 19 | * @param instance 20 | */ 21 | public setInstance(type: MapTypeEnum, instance:any) { 22 | this.mapInstanceMap.set(type, instance); 23 | } 24 | } 25 | export default new CommonStore(); 26 | -------------------------------------------------------------------------------- /src/shims-vue.d.ts: -------------------------------------------------------------------------------- 1 | declare module '*.vue' { 2 | import Vue from 'vue'; 3 | export default Vue; 4 | } 5 | declare module 'qs' { 6 | const qs: any; 7 | export default qs; 8 | } 9 | 10 | declare module '$Message' { 11 | export const $Message: any; 12 | } 13 | 14 | declare module '$Modal' { 15 | export const $Modal: any; 16 | } 17 | 18 | declare module '$router' { 19 | export const $router: any; 20 | } 21 | 22 | declare module 'el-tree-transfer' { 23 | export const treeTransfer: any; 24 | } 25 | 26 | declare module 'vue2-org-tree' { 27 | export const Vue2OrgTree: any; 28 | } 29 | declare module 'el-tree-select' { 30 | export const ElTreeSelect: any; 31 | } 32 | declare module 'vue-fontawesome-elementui-icon-picker' { 33 | export const iconPicker: any; 34 | } 35 | -------------------------------------------------------------------------------- /src/map/service/cesium/imageryProvider/tdt/TdtImageryProvider.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * 天地图 3 | */ 4 | import { UrlTemplateImageryProvider, WebMercatorTilingScheme } from 'cesium'; 5 | 6 | const MAP_URL = 'https://t{s}.tianditu.gov.cn/DataServer?T={style}_w&x={x}&y={y}&l={z}&tk={key}'; 7 | 8 | class TdtImageryProvider extends UrlTemplateImageryProvider { 9 | constructor(options: any = {}) { 10 | super({ 11 | url: MAP_URL.replace(/\{style\}/g, options.style || 'vec').replace( 12 | /\{key\}/g, 13 | options.key || '' 14 | ), 15 | subdomains: ['0', '1', '2', '3', '4', '5', '6', '7'], 16 | tilingScheme: new WebMercatorTilingScheme(), 17 | maximumLevel: 18 18 | }); 19 | } 20 | } 21 | 22 | export default TdtImageryProvider; 23 | -------------------------------------------------------------------------------- /src/views/pug/Pug.vue: -------------------------------------------------------------------------------- 1 | 25 | 26 | 32 | 33 | 38 | -------------------------------------------------------------------------------- /src/map/service/leaflet/markerCluster/LeafletMarkerCluster.ts: -------------------------------------------------------------------------------- 1 | import 'leaflet.markercluster/dist/MarkerCluster.css'; 2 | import 'leaflet.markercluster/dist/MarkerCluster.Default.css'; 3 | import 'leaflet.markercluster'; 4 | import { Marker } from 'leaflet'; 5 | 6 | 7 | class LeafletMarkerCluster { 8 | public L: any; 9 | 10 | constructor(L: any) { 11 | this.L = L; 12 | } 13 | 14 | /** 15 | * 创建聚合 16 | * @param markers 17 | */ 18 | public createClusterMarker(markers: Marker[]) { 19 | const createMakerCluster = this.L.markerClusterGroup(); 20 | console.log(createMakerCluster); 21 | for (let i = 0; i < markers.length; i++) { 22 | createMakerCluster.addLayer(markers[i]); 23 | } 24 | return createMakerCluster; 25 | } 26 | } 27 | 28 | export default LeafletMarkerCluster; 29 | -------------------------------------------------------------------------------- /src/puglin/LoadingPluginService.ts: -------------------------------------------------------------------------------- 1 | import { Loading } from 'element-ui'; 2 | 3 | class LoadingPluginService { 4 | public loading: any; 5 | constructor() {} 6 | 7 | /** 8 | * 开启加载 9 | */ 10 | public startLoading() { 11 | console.log(this.loading); 12 | this.closeLoading(); 13 | this.loading = Loading.service({ 14 | lock: true, 15 | body: true, 16 | customClass: 'app-custom-loading', 17 | text: '计算中......',//加载动画的文字 18 | background: 'rgba(0, 0, 0, 0.7)'//加载动画的背景 19 | }); 20 | console.log(this.loading); 21 | } 22 | 23 | /** 24 | * 关闭加载 25 | */ 26 | public closeLoading() { 27 | if (this.loading) { 28 | this.loading.close(); 29 | } 30 | } 31 | } 32 | 33 | export default new LoadingPluginService(); 34 | -------------------------------------------------------------------------------- /src/components/layouts/BaseLayout.vue: -------------------------------------------------------------------------------- 1 | 5 | 6 | 23 | 24 | 32 | -------------------------------------------------------------------------------- /src/components/controlWidget/LayerControlWidget.vue: -------------------------------------------------------------------------------- 1 | 5 | 6 | 22 | 23 | 37 | -------------------------------------------------------------------------------- /src/components/controlWidget/CommonIconDialog.vue: -------------------------------------------------------------------------------- 1 | 5 | 6 | 21 | 22 | 39 | -------------------------------------------------------------------------------- /src/components/mini/HelloWorldComponent.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 33 | 34 | 40 | -------------------------------------------------------------------------------- /src/map/type/CesiumType.ts: -------------------------------------------------------------------------------- 1 | export interface CesiumInstanceOptions { 2 | id: string; 3 | animation?: boolean; //是否创建动画小器件,左下角仪表 4 | baseLayerPicker?: boolean; //是否显示图层选择器 5 | fullscreenButton?: boolean; //是否显示全屏按钮 6 | vrButton?: boolean; // 是否显示VR按钮 7 | geocoder?: boolean; // 是否显示geocoder小器件,右上角查询按钮 8 | homeButton?: boolean; //是否显示Home按钮 9 | infoBox?: boolean; //是否显示信息框 10 | sceneModePicker?: boolean; // 是否显示3D/2D选择器 11 | selectionIndicator?: boolean; // 是否显示选取指示器组件 12 | timeline?: boolean; // 是否显示时间轴 13 | navigationHelpButton?: boolean; // 是否显示右上角的帮助按钮 14 | scene3DOnly?: boolean // 如果设置为true,则所有几何图形以3D模式绘制以节约GPU资源 15 | navigationInstructionsInitiallyVisible?: boolean; 16 | showRenderLoopErrors?: boolean; 17 | //加载自定义地图瓦片需要指定一个自定义图片服务器 例如指定OpenStreetMapImagerProvider 18 | //URL 为瓦片数据服务器地址 19 | imageryProvider?: any; //UrlTemplateImageryProvider 20 | templateImageLayerUrl?: string; 21 | enableLighting?: boolean; // 是否启用照明 22 | } 23 | -------------------------------------------------------------------------------- /tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "esnext", 4 | "module": "esnext", 5 | "strict": true, 6 | "jsx": "preserve", 7 | "importHelpers": true, 8 | "moduleResolution": "node", 9 | "experimentalDecorators": true, 10 | "esModuleInterop": true, 11 | "allowSyntheticDefaultImports": true, 12 | "strictPropertyInitialization": false, 13 | "sourceMap": true, 14 | "baseUrl": ".", 15 | "types": [ 16 | "webpack-env", 17 | "jest" 18 | ], 19 | "paths": { 20 | "@/*": [ 21 | "src/*" 22 | ] 23 | }, 24 | "lib": [ 25 | "esnext", 26 | "dom", 27 | "dom.iterable", 28 | "scripthost" 29 | ] 30 | }, 31 | "include": [ 32 | "src/**/*.ts", 33 | "src/**/*.tsx", 34 | "src/**/*.vue", 35 | "tests/**/*.ts", 36 | "tests/**/*.tsx" 37 | ], 38 | "exclude": [ 39 | "node_modules" 40 | ] 41 | } 42 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "esnext", 4 | "module": "esnext", 5 | "strict": true, 6 | "jsx": "preserve", 7 | "importHelpers": true, 8 | "moduleResolution": "node", 9 | "experimentalDecorators": true, 10 | "resolveJsonModule": true, 11 | "esModuleInterop": true, 12 | "allowSyntheticDefaultImports": true, 13 | "strictPropertyInitialization": false, 14 | "sourceMap": true, 15 | "baseUrl": ".", 16 | "types": [ 17 | "@types/leaflet", 18 | "@types/mapbox-gl", 19 | "@types/cesium", 20 | "@types/node" 21 | ], 22 | "paths": { 23 | "@/*": [ 24 | "src/*" 25 | ] 26 | }, 27 | "lib": [ 28 | "esnext", 29 | "dom", 30 | "dom.iterable", 31 | "scripthost" 32 | ] 33 | }, 34 | "include": [ 35 | "src/**/*.ts", 36 | "src/**/*.tsx", 37 | "src/**/*.vue", 38 | "tests/**/*.ts", 39 | "tests/**/*.tsx" 40 | ], 41 | "exclude": [ 42 | "node_modules" 43 | ] 44 | } 45 | -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 7 | 8 | 9 | 模板系统V1.0 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /src/map/service/cesium/imageryProvider/amap/AmapImageryProvider.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * 高德地图 3 | */ 4 | import { UrlTemplateImageryProvider } from 'cesium'; 5 | import AmapMercatorTilingScheme from './AmapMercatorTilingScheme'; 6 | 7 | const IMG_URL: string = 'https://webst{s}.is.autonavi.com/appmaptile?style=6&x={x}&y={y}&z={z}'; 8 | 9 | const ELEC_URL: string = 'https://webrd{s}.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=8&x={x}&y={y}&z={z}'; 10 | 11 | const CVA_URL: string = 'https://webst{s}.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=8&x={x}&y={y}&z={z}'; 12 | 13 | class AmapImageryProvider extends UrlTemplateImageryProvider { 14 | constructor(options: any = {}) { 15 | options['url'] = 16 | options.style === 'img' 17 | ? IMG_URL 18 | : options.style === 'cva' 19 | ? CVA_URL 20 | : ELEC_URL; 21 | if (!options.subdomains || !options.subdomains.length) { 22 | options['subdomains'] = ['01', '02', '03', '04']; 23 | } 24 | if (options.crs === 'WGS84') { 25 | options['tilingScheme'] = new AmapMercatorTilingScheme(); 26 | } 27 | super(options); 28 | } 29 | } 30 | export default AmapImageryProvider; 31 | -------------------------------------------------------------------------------- /src/views/home/HomeList.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 39 | 40 | 44 | -------------------------------------------------------------------------------- /src/components/aside/SlideTree.vue: -------------------------------------------------------------------------------- 1 | 13 | 14 | 27 | 28 | 33 | -------------------------------------------------------------------------------- /src/components/Map/MapBoxView.vue: -------------------------------------------------------------------------------- 1 | 5 | 6 | 40 | 41 | 51 | -------------------------------------------------------------------------------- /src/map/common/pugin/echartslayer-libs/lib/EchartsLayer.js: -------------------------------------------------------------------------------- 1 | function EchartsLayer(map) { 2 | const mapContainer = map.getCanvasContainer(); 3 | this._container = document.createElement('div'); 4 | this._container.style.width = map.getCanvas().style.width; 5 | this._container.style.height = map.getCanvas().style.height; 6 | this._container.setAttribute('id', 'echarts'); 7 | this._container.setAttribute('class', 'echartMap'); 8 | this._map = map; 9 | mapContainer.appendChild(this._container); 10 | this.chart = echarts.init(this._container); 11 | echarts.glMap = map; 12 | this.resize(); 13 | } 14 | EchartsLayer.prototype.remove = function() { 15 | var _this = this; 16 | this._map._listeners.move.forEach(function(element) { 17 | if (element.name === 'moveHandler') { 18 | _this._map.off('move', element); 19 | } 20 | }); 21 | this._map._listeners.move.forEach(function(element) { 22 | if (element.name === 'zoomEndHandler') { 23 | _this._map.off('zoomend', element); 24 | } 25 | }); 26 | 27 | // this._map.off('move', this._map._listeners.move[1]); 28 | // this._map.off('zoomend', this._map._listeners.moveend[1]); 29 | this.chart.clear(); 30 | if(this._container.parentNode) 31 | this._container.parentNode.removeChild(this._container); 32 | this._map = undefined; 33 | }; 34 | EchartsLayer.prototype.resize = function() { 35 | const me = this; 36 | window.onresize = function() { 37 | me._container.style.width = me._map.getCanvas().style.width; 38 | me._container.style.height = me._map.getCanvas().style.height; 39 | me.chart.resize(); 40 | }; 41 | }; 42 | module.exports = EchartsLayer; 43 | -------------------------------------------------------------------------------- /src/map/service/cesium/imageryProvider/amap/AmapMercatorTilingScheme.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * 高德地图图层 3 | */ 4 | import { WebMercatorTilingScheme, WebMercatorProjection, Math, Cartographic, Cartesian2 } from 'cesium'; 5 | import CoordTransform from '../../../../utils/CoordTransform'; 6 | 7 | class AmapMercatorTilingScheme extends WebMercatorTilingScheme { 8 | constructor(options: any = {}) { 9 | super(options); 10 | let projection: WebMercatorProjection = new WebMercatorProjection(); 11 | (this.projection as any).project = function(cartographic: any, result: any) { 12 | result = CoordTransform.WGS84ToGCJ02( 13 | Math.toDegrees(cartographic.longitude), 14 | Math.toDegrees(cartographic.latitude) 15 | ); 16 | result = projection.project( 17 | new Cartographic( 18 | Math.toRadians(result[0]), 19 | Math.toRadians(result[1]) 20 | ) 21 | ); 22 | return new Cartesian2(result.x, result.y); 23 | }; 24 | (this.projection as any).unproject = function(cartesian: any, result: any) { 25 | let cartographic = projection.unproject(cartesian); 26 | result = CoordTransform.GCJ02ToWGS84( 27 | Math.toDegrees(cartographic.longitude), 28 | Math.toDegrees(cartographic.latitude) 29 | ); 30 | return new Cartographic( 31 | Math.toRadians(result[0]), 32 | Math.toRadians(result[1]) 33 | ); 34 | }; 35 | } 36 | } 37 | 38 | export default AmapMercatorTilingScheme; 39 | -------------------------------------------------------------------------------- /src/map/service/mapbox/pugin/echartslayer-libs/lib/EchartsLayer.js: -------------------------------------------------------------------------------- 1 | function EchartsLayer(map) { 2 | const mapContainer = map.getCanvasContainer(); 3 | this._container = document.createElement('div'); 4 | this._container.style.width = map.getCanvas().style.width; 5 | this._container.style.height = map.getCanvas().style.height; 6 | this._container.setAttribute('id', 'echarts'); 7 | this._container.setAttribute('class', 'echartMap'); 8 | this._map = map; 9 | mapContainer.appendChild(this._container); 10 | this.chart = echarts.init(this._container); 11 | echarts.glMap = map; 12 | this.resize(); 13 | } 14 | EchartsLayer.prototype.remove = function() { 15 | var _this = this; 16 | this._map._listeners.move.forEach(function(element) { 17 | if (element.name === 'moveHandler') { 18 | _this._map.off('move', element); 19 | } 20 | }); 21 | this._map._listeners.move.forEach(function(element) { 22 | if (element.name === 'zoomEndHandler') { 23 | _this._map.off('zoomend', element); 24 | } 25 | }); 26 | 27 | // this._map.off('move', this._map._listeners.move[1]); 28 | // this._map.off('zoomend', this._map._listeners.moveend[1]); 29 | this.chart.clear(); 30 | if(this._container.parentNode) 31 | this._container.parentNode.removeChild(this._container); 32 | this._map = undefined; 33 | }; 34 | EchartsLayer.prototype.resize = function() { 35 | const me = this; 36 | window.onresize = function() { 37 | me._container.style.width = me._map.getCanvas().style.width; 38 | me._container.style.height = me._map.getCanvas().style.height; 39 | me.chart.resize(); 40 | }; 41 | }; 42 | module.exports = EchartsLayer; 43 | -------------------------------------------------------------------------------- /src/components/aside/Index.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 42 | 43 | 51 | -------------------------------------------------------------------------------- /src/map/type/CommonType.ts: -------------------------------------------------------------------------------- 1 | import { CesiumInstanceOptions } from '../type/CesiumType'; 2 | import { LeafletInstanceOptions } from '../type/LeafletType'; 3 | import { MapBoxInstanceOptions } from '../type/MapBoxType'; 4 | 5 | export const MapTypeList: MapTypeEnum[] = ['CESIUM', 'LEAFLET', 'MAPBOX']; 6 | /** 7 | * 地图类型 8 | */ 9 | export type MapTypeEnum = 'CESIUM' | 'LEAFLET' | 'MAPBOX'; 10 | 11 | /** 12 | * 图层类型 13 | */ 14 | export type LayerImagesEnum = 15 | 'AMAP' | 'BAIDU' | 'TIANDITU' | 'GOOGLEMAP' | 16 | '高德地图' | '高德影像' | 17 | '天地图' | '天地图影像' | '天地图地形' | 'Google地图' | 'Google影像' | 'GeoQ' | 'GeoQ藏蓝' | 'GeoQ灰'; 18 | 19 | /** 20 | * 点位坐标 21 | */ 22 | export interface MapPoint { 23 | lng: any; 24 | lat: any; 25 | } 26 | /** 27 | * 地图初始化参数 28 | */ 29 | export type MapInitOptions = CesiumInstanceOptions | LeafletInstanceOptions | MapBoxInstanceOptions; 30 | 31 | /** 32 | * 坐标系 33 | */ 34 | export type CrsConfigEnum = 'WGS84' | 'BD09' | 'GCJ02'; 35 | /** 36 | * 图层样式 37 | */ 38 | export type LayerCesiumStyleConfigEnum = 'img' | 'elec' | 'cva' | 'vec'; 39 | /** 40 | * 图层修改配置 41 | */ 42 | export interface ChangeLayerImageConfig { 43 | style: LayerCesiumStyleConfigEnum, // style: img、elec、cva 44 | crs: CrsConfigEnum // 使用84坐标系,默认为:GCJ02 45 | } 46 | /** 47 | * 地图对外暴露的方法 48 | */ 49 | export abstract class BaseMap { 50 | /** 51 | * 初始化地图 52 | * @param type 53 | * @param props 54 | */ 55 | abstract initMapInstance(type: MapTypeEnum, props: CesiumInstanceOptions): any; 56 | 57 | /** 58 | * 修改底图 59 | * @param type 60 | * @param config 61 | * @param instance 62 | */ 63 | abstract changeLayer(type: LayerImagesEnum, config: ChangeLayerImageConfig, instance: any): any; 64 | } 65 | -------------------------------------------------------------------------------- /src/store/module/app.ts: -------------------------------------------------------------------------------- 1 | import { Module, VuexModule, Mutation, Action, getModule, MutationAction } from 'vuex-module-decorators'; 2 | import { MapTypeEnum } from '@/map/type/CommonType'; 3 | import CesiumService from '@/map/service/CesiumService'; 4 | import LeafletService from '@/map/service/LeafletService'; 5 | import MapBoxService from '@/map/service/MapBoxService'; 6 | 7 | @Module({ 8 | name: 'appModule', 9 | namespaced: true, 10 | // stateFactory: true 11 | }) 12 | export default class AppStoreModule extends VuexModule { 13 | public vuexStatus: number = 0; 14 | 15 | public mapType: MapTypeEnum = 'MAPBOX'; 16 | 17 | private cesiumMapInstance: CesiumService | null = null; 18 | 19 | public leafletMapInstance: LeafletService | null = null; 20 | 21 | public mapBoxMapInstance: MapBoxService | null = null; 22 | 23 | @Mutation 24 | public setVuexStatus(val: number) { 25 | this.vuexStatus = val; 26 | } 27 | 28 | @Mutation 29 | public setMapInstance(data: { mapType: MapTypeEnum, instance: any }) { 30 | switch (data.mapType) { 31 | case 'CESIUM': 32 | this.cesiumMapInstance = data.instance; 33 | break; 34 | case 'LEAFLET': 35 | this.leafletMapInstance = data.instance; 36 | break; 37 | case 'MAPBOX': 38 | this.mapBoxMapInstance = data.instance; 39 | break; 40 | } 41 | } 42 | 43 | @Mutation 44 | public setMapType(val: MapTypeEnum) { 45 | this.mapType = val; 46 | } 47 | 48 | @Action({ commit: 'setVuexStatus' }) 49 | public commitVuexStatus() { 50 | return 6; 51 | } 52 | 53 | get vuexStoreValue() { 54 | return this.vuexStatus; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/components/dialog/popUp/commonWidget/VuePointDetailComponent.vue: -------------------------------------------------------------------------------- 1 | 11 | 12 | 34 | 35 | 64 | -------------------------------------------------------------------------------- /src/map/common/pugin/echartslayer-libs/lib/GLMapCoordSys.js: -------------------------------------------------------------------------------- 1 | define(function (require) { 2 | var echarts = require('echarts') 3 | 4 | function GLMapCoordSys (GLMap, api) { 5 | this._GLMap = GLMap 6 | this.dimensions = ['lng', 'lat'] 7 | this._mapOffset = [0, 0] 8 | 9 | this._api = api 10 | } 11 | 12 | GLMapCoordSys.prototype.dimensions = ['lng', 'lat'] 13 | 14 | GLMapCoordSys.prototype.setMapOffset = function (mapOffset) { 15 | this._mapOffset = mapOffset 16 | } 17 | 18 | GLMapCoordSys.prototype.getBMap = function () { 19 | return this._GLMap 20 | } 21 | 22 | GLMapCoordSys.prototype.dataToPoint = function (data) { 23 | var px = this._GLMap.project(data) 24 | 25 | var mapOffset = this._mapOffset 26 | 27 | return [px.x - mapOffset[0], px.y - mapOffset[1]] 28 | } 29 | 30 | GLMapCoordSys.prototype.pointToData = function (pt) { 31 | var mapOffset = this._mapOffset 32 | var pt = this._bmap.project( 33 | [ pt[0] + mapOffset[0], 34 | pt[1] + mapOffset[1]] 35 | ) 36 | return [pt.lng, pt.lat] 37 | } 38 | 39 | GLMapCoordSys.prototype.getViewRect = function () { 40 | var api = this._api 41 | return new echarts.graphic.BoundingRect(0, 0, api.getWidth(), api.getHeight()) 42 | } 43 | 44 | GLMapCoordSys.prototype.getRoamTransform = function () { 45 | return echarts.matrix.create() 46 | } 47 | 48 | 49 | // For deciding which dimensions to use when creating list data 50 | GLMapCoordSys.dimensions = GLMapCoordSys.prototype.dimensions 51 | 52 | GLMapCoordSys.create = function (ecModel, api) { 53 | var coordSys; 54 | 55 | ecModel.eachComponent('GLMap', function (GLMapModel) { 56 | var viewportRoot = api.getZr().painter.getViewportRoot() 57 | var GLMap = echarts.glMap; 58 | coordSys = new GLMapCoordSys(GLMap, api) 59 | coordSys.setMapOffset(GLMapModel.__mapOffset || [0, 0]) 60 | GLMapModel.coordinateSystem = coordSys 61 | }) 62 | 63 | ecModel.eachSeries(function (seriesModel) { 64 | if (seriesModel.get('coordinateSystem') === 'GLMap') { 65 | seriesModel.coordinateSystem = coordSys 66 | } 67 | }) 68 | } 69 | 70 | return GLMapCoordSys 71 | }) 72 | -------------------------------------------------------------------------------- /src/components/Map/LeafletView.vue: -------------------------------------------------------------------------------- 1 | 5 | 6 | 42 | 43 | 52 | 71 | -------------------------------------------------------------------------------- /src/map/service/mapbox/pugin/echartslayer-libs/lib/GLMapCoordSys.js: -------------------------------------------------------------------------------- 1 | define(function (require) { 2 | var echarts = require('echarts') 3 | 4 | function GLMapCoordSys (GLMap, api) { 5 | this._GLMap = GLMap 6 | this.dimensions = ['lng', 'lat'] 7 | this._mapOffset = [0, 0] 8 | 9 | this._api = api 10 | } 11 | 12 | GLMapCoordSys.prototype.dimensions = ['lng', 'lat'] 13 | 14 | GLMapCoordSys.prototype.setMapOffset = function (mapOffset) { 15 | this._mapOffset = mapOffset 16 | } 17 | 18 | GLMapCoordSys.prototype.getBMap = function () { 19 | return this._GLMap 20 | } 21 | 22 | GLMapCoordSys.prototype.dataToPoint = function (data) { 23 | var px = this._GLMap.project(data) 24 | 25 | var mapOffset = this._mapOffset 26 | 27 | return [px.x - mapOffset[0], px.y - mapOffset[1]] 28 | } 29 | 30 | GLMapCoordSys.prototype.pointToData = function (pt) { 31 | var mapOffset = this._mapOffset 32 | var pt = this._bmap.project( 33 | [ pt[0] + mapOffset[0], 34 | pt[1] + mapOffset[1]] 35 | ) 36 | return [pt.lng, pt.lat] 37 | } 38 | 39 | GLMapCoordSys.prototype.getViewRect = function () { 40 | var api = this._api 41 | return new echarts.graphic.BoundingRect(0, 0, api.getWidth(), api.getHeight()) 42 | } 43 | 44 | GLMapCoordSys.prototype.getRoamTransform = function () { 45 | return echarts.matrix.create() 46 | } 47 | 48 | 49 | // For deciding which dimensions to use when creating list data 50 | GLMapCoordSys.dimensions = GLMapCoordSys.prototype.dimensions 51 | 52 | GLMapCoordSys.create = function (ecModel, api) { 53 | var coordSys; 54 | 55 | ecModel.eachComponent('GLMap', function (GLMapModel) { 56 | var viewportRoot = api.getZr().painter.getViewportRoot() 57 | var GLMap = echarts.glMap; 58 | coordSys = new GLMapCoordSys(GLMap, api) 59 | coordSys.setMapOffset(GLMapModel.__mapOffset || [0, 0]) 60 | GLMapModel.coordinateSystem = coordSys 61 | }) 62 | 63 | ecModel.eachSeries(function (seriesModel) { 64 | if (seriesModel.get('coordinateSystem') === 'GLMap') { 65 | seriesModel.coordinateSystem = coordSys 66 | } 67 | }) 68 | } 69 | 70 | return GLMapCoordSys 71 | }) 72 | -------------------------------------------------------------------------------- /src/map/common/pugin/echartslayer-libs/lib/GLMapView.js: -------------------------------------------------------------------------------- 1 | define(function (require) { 2 | return require('echarts').extendComponentView({ 3 | type: 'GLMap', 4 | 5 | render: function (GLMapModel, ecModel, api) { 6 | var rendering = true 7 | 8 | var glMap = echarts.glMap 9 | 10 | 11 | var viewportRoot = api.getZr().painter.getViewportRoot() 12 | var coordSys = GLMapModel.coordinateSystem 13 | var moveHandler = function (type, target) { 14 | if (rendering) { 15 | return 16 | } 17 | // var offsetEl = viewportRoot.parentNode.parentNode.parentNode 18 | var offsetEl = document.getElementsByClassName('mapboxgl-map')[0]; 19 | 20 | var mapOffset = [ 21 | -parseInt(offsetEl.style.left, 10) || 0, 22 | -parseInt(offsetEl.style.top, 10) || 0 23 | ] 24 | viewportRoot.style.left = mapOffset[0] + 'px' 25 | viewportRoot.style.top = mapOffset[1] + 'px' 26 | 27 | coordSys.setMapOffset(mapOffset) 28 | GLMapModel.__mapOffset = mapOffset 29 | 30 | api.dispatchAction({ 31 | type: 'GLMapRoam' 32 | }) 33 | } 34 | 35 | function zoomEndHandler () { 36 | if (rendering) { 37 | return 38 | } 39 | api.dispatchAction({ 40 | type: 'GLMapRoam' 41 | }) 42 | } 43 | 44 | glMap.off('move', this._oldMoveHandler) 45 | // FIXME 46 | // Moveend may be triggered by centerAndZoom method when creating coordSys next time 47 | // glMap.removeEventListener('moveend', this._oldMoveHandler) 48 | glMap.off('zoomend', this._oldZoomEndHandler) 49 | glMap.on('move', moveHandler) 50 | // glMap.addEventListener('moveend', moveHandler) 51 | glMap.on('zoomend', zoomEndHandler) 52 | 53 | this._oldMoveHandler = moveHandler 54 | this._oldZoomEndHandler = zoomEndHandler 55 | 56 | var roam = GLMapModel.get('roam') 57 | if (roam && roam !== 'scale') { 58 | // todo 允许拖拽 59 | }else { 60 | // todo 不允许拖拽 61 | } 62 | if (roam && roam !== 'move') { 63 | // todo 允许移动 64 | }else { 65 | // todo 不允许允许移动 66 | } 67 | 68 | 69 | 70 | rendering = false 71 | } 72 | }) 73 | }) 74 | -------------------------------------------------------------------------------- /src/map/service/mapbox/pugin/echartslayer-libs/lib/GLMapView.js: -------------------------------------------------------------------------------- 1 | define(function (require) { 2 | return require('echarts').extendComponentView({ 3 | type: 'GLMap', 4 | 5 | render: function (GLMapModel, ecModel, api) { 6 | var rendering = true 7 | 8 | var glMap = echarts.glMap 9 | 10 | 11 | var viewportRoot = api.getZr().painter.getViewportRoot() 12 | var coordSys = GLMapModel.coordinateSystem 13 | var moveHandler = function (type, target) { 14 | if (rendering) { 15 | return 16 | } 17 | // var offsetEl = viewportRoot.parentNode.parentNode.parentNode 18 | var offsetEl = document.getElementsByClassName('mapboxgl-map')[0]; 19 | 20 | var mapOffset = [ 21 | -parseInt(offsetEl.style.left, 10) || 0, 22 | -parseInt(offsetEl.style.top, 10) || 0 23 | ] 24 | viewportRoot.style.left = mapOffset[0] + 'px' 25 | viewportRoot.style.top = mapOffset[1] + 'px' 26 | 27 | coordSys.setMapOffset(mapOffset) 28 | GLMapModel.__mapOffset = mapOffset 29 | 30 | api.dispatchAction({ 31 | type: 'GLMapRoam' 32 | }) 33 | } 34 | 35 | function zoomEndHandler () { 36 | if (rendering) { 37 | return 38 | } 39 | api.dispatchAction({ 40 | type: 'GLMapRoam' 41 | }) 42 | } 43 | 44 | glMap.off('move', this._oldMoveHandler) 45 | // FIXME 46 | // Moveend may be triggered by centerAndZoom method when creating coordSys next time 47 | // glMap.removeEventListener('moveend', this._oldMoveHandler) 48 | glMap.off('zoomend', this._oldZoomEndHandler) 49 | glMap.on('move', moveHandler) 50 | // glMap.addEventListener('moveend', moveHandler) 51 | glMap.on('zoomend', zoomEndHandler) 52 | 53 | this._oldMoveHandler = moveHandler 54 | this._oldZoomEndHandler = zoomEndHandler 55 | 56 | var roam = GLMapModel.get('roam') 57 | if (roam && roam !== 'scale') { 58 | // todo 允许拖拽 59 | }else { 60 | // todo 不允许拖拽 61 | } 62 | if (roam && roam !== 'move') { 63 | // todo 允许移动 64 | }else { 65 | // todo 不允许允许移动 66 | } 67 | 68 | 69 | 70 | rendering = false 71 | } 72 | }) 73 | }) 74 | -------------------------------------------------------------------------------- /src/style/main.css: -------------------------------------------------------------------------------- 1 | @charset "UTF-8"; 2 | /* reset */ 3 | html, body, div, h1, h2, h3, h4, h5, h6, p, dl, dt, dd, ol, ul, li, fieldset, form, label, input, legend, table, caption, tbody, tfoot, thead, tr, th, td, textarea, article, aside, audio, canvas, figure, footer, header, mark, menu, nav, section, time, video { 4 | margin: 0; 5 | padding: 0; 6 | } 7 | 8 | html { 9 | min-width: 1200px; 10 | } 11 | 12 | html, body { 13 | height: 100%; 14 | } 15 | 16 | h1, h2, h3, h4, h5, h6 { 17 | font-size: 100%; 18 | font-weight: normal 19 | } 20 | 21 | body { 22 | font-size: 14px; 23 | line-height: 1; 24 | font-family: "Microsoft YaHei", "Helvetica Neue", "Helvetica", Arial, sans-serif; 25 | background-color: #fff; 26 | color: #333; 27 | } 28 | 29 | article, aside, dialog, figure, footer, header, hgroup, nav, section, blockquote { 30 | display: block; 31 | } 32 | 33 | ul, ol { 34 | list-style: none; 35 | } 36 | 37 | img { 38 | border: 0 none; 39 | vertical-align: top; 40 | } 41 | 42 | table { 43 | border-collapse: collapse; 44 | border-spacing: 0; 45 | } 46 | 47 | strong, em, i { 48 | font-style: normal; 49 | font-weight: normal; 50 | } 51 | 52 | ins { 53 | text-decoration: underline; 54 | } 55 | 56 | del { 57 | text-decoration: line-through; 58 | } 59 | 60 | mark { 61 | background: none; 62 | } 63 | 64 | input::-ms-clear { 65 | display: none !important; 66 | } 67 | 68 | input, select, textarea, button { 69 | vertical-align: middle; 70 | outline: none; 71 | border: 0; 72 | } 73 | 74 | input { 75 | border-radius: 0; 76 | box-shadow: none; 77 | } 78 | 79 | input[type="button"], 80 | input[type="submit"], 81 | input[type="reset"], 82 | button { 83 | -webkit-appearance: none; 84 | } 85 | 86 | textarea { 87 | -webkit-appearance: none; 88 | overflow-y: auto; 89 | overflow-x: hidden; 90 | resize: none; 91 | } 92 | 93 | /* 如果需要去除掉select元素的默认样式,放开下面的注释即可 */ 94 | select { 95 | appearance: none; 96 | -ms-appearance: none; 97 | -moz-appearance: none; 98 | -webkit-appearance: none; 99 | } 100 | 101 | select::-ms-expand { 102 | display: none; 103 | } 104 | 105 | a:link, a:visited { 106 | text-decoration: none; 107 | color: #333; 108 | } 109 | 110 | a:hover, a:active { 111 | text-decoration: none; 112 | } 113 | -------------------------------------------------------------------------------- /src/data/gltf/rectangle.gltf: -------------------------------------------------------------------------------- 1 | {"accessors":[{"name":"object_1_1_positions","componentType":5126,"count":24,"min":[-5,0,-3],"max":[5,14,3],"type":"VEC3","bufferView":0,"byteOffset":0},{"name":"object_1_1_normals","componentType":5126,"count":24,"min":[-1,-1,-1],"max":[1,1,1],"type":"VEC3","bufferView":0,"byteOffset":288},{"name":"object_1_1_texcoords","componentType":5126,"count":24,"min":[0,0],"max":[1,1],"type":"VEC2","bufferView":1,"byteOffset":0},{"name":"object_1_1_0_indices","componentType":5123,"count":36,"min":[0],"max":[23],"type":"SCALAR","bufferView":2,"byteOffset":0}],"asset":{"generator":"obj2gltf","version":"2.0"},"buffers":[{"name":"building_Rectangle","byteLength":840,"uri":"data:application\/octet-stream;base64,AACgwAAAAAAAAEBAAACgQAAAAAAAAEBAAACgQAAAYEEAAEBAAACgwAAAYEEAAEBAAACgQAAAAAAAAEBAAACgQAAAAAAAAEDAAACgQAAAYEEAAEDAAACgQAAAYEEAAEBAAACgQAAAAAAAAEDAAACgwAAAAAAAAEDAAACgwAAAYEEAAEDAAACgQAAAYEEAAEDAAACgwAAAAAAAAEDAAACgwAAAAAAAAEBAAACgwAAAYEEAAEBAAACgwAAAYEEAAEDAAACgQAAAAAAAAEBAAACgwAAAAAAAAEBAAACgwAAAAAAAAEDAAACgQAAAAAAAAEDAAACgQAAAYEEAAEBAAACgwAAAYEEAAEDAAACgwAAAYEEAAEBAAACgQAAAYEEAAEDAAAAAAAAAAAAAAIA\/AAAAAAAAAAAAAIA\/AAAAAAAAAAAAAIA\/AAAAAAAAAAAAAIA\/AACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAAAAAAIC\/AAAAAAAAAAAAAIC\/AAAAAAAAAAAAAIC\/AAAAAAAAAAAAAIC\/AACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAKA+AACAPwAAoD7sTmw+AAAAAOxObD4AAKA+AACAPwAAAD8AAIA\/AAAAP+xObD4AAKA+7E5sPgAAAD8AAIA\/AABQPwAAgD8AAFA\/7E5sPgAAAD\/sTmw+AABQPwAAgD8AAIA\/AACAPwAAgD\/sTmw+AABQP+xObD4AAKA+AAAAAAAAAAAAAAAAAAAAALhObD4AAKA+uE5sPgAAgD+4Tmw+AAAwPwAAAAAAADA\/uE5sPgAAgD8AAAAAAAABAAIAAAACAAMABAAFAAYABAAGAAcACAAJAAoACAAKAAsADAANAA4ADAAOAA8AEAARABIAEgATABAAFAAVABYAFQAUABcA"}],"bufferViews":[{"name":"bufferView_0","buffer":0,"byteLength":576,"byteOffset":0,"byteStride":12,"target":34962},{"name":"bufferView_1","buffer":0,"byteLength":192,"byteOffset":576,"byteStride":8,"target":34962},{"name":"bufferView_2","buffer":0,"byteLength":72,"byteOffset":768,"target":34963}],"materials":[{"name":"Default","pbrMetallicRoughness":{"baseColorFactor":[1,1,1,1],"metallicFactor":0,"roughnessFactor":1},"emissiveFactor":[0,0,0],"alphaMode":"OPAQUE","doubleSided":false}],"meshes":[{"name":"object_1_1","primitives":[{"attributes":{"POSITION":0,"NORMAL":1,"TEXCOORD_0":2},"indices":3,"material":0,"mode":4}]}],"nodes":[{"name":"object_1","mesh":0}],"scene":0,"scenes":[{"nodes":[0]}]} -------------------------------------------------------------------------------- /src/components/dialog/popUp/CesiumPopUpDialog.vue: -------------------------------------------------------------------------------- 1 | 17 | 18 | 54 | 55 | 84 | -------------------------------------------------------------------------------- /src/components/dialog/popUp/MapboxPopUpDialog.vue: -------------------------------------------------------------------------------- 1 | 17 | 18 | 54 | 55 | 84 | -------------------------------------------------------------------------------- /src/components/dialog/popUp/LeafletPopUpDialog.vue: -------------------------------------------------------------------------------- 1 | 17 | 18 | 54 | 55 | 84 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "parser": "vue-eslint-parser", 3 | "plugins": [ 4 | "vue" 5 | ], 6 | "extends": [ 7 | "eslint:recommended", 8 | "plugin:vue/recommended", 9 | "prettier" 10 | ], 11 | "parserOptions": { 12 | "parser": "@typescript-eslint/parser", 13 | "sourceType": "module", 14 | "ecmaVersion": 6, 15 | "ecmaFeatures": { 16 | "jsx": true, 17 | "legacyDecorators": true 18 | } 19 | }, 20 | "env": { 21 | "browser": true, 22 | "amd": true, 23 | "es6": true, 24 | "node": true, 25 | "mocha": true 26 | }, 27 | "globals": { 28 | "L": true 29 | }, 30 | "rules": { 31 | "no-prototype-builtins": [0], 32 | "no-console": [ 33 | 0 34 | ], 35 | "rest-spread-spacing": [ 36 | 2 37 | ], 38 | "key-spacing": [ 39 | 2 40 | ], 41 | "space-infix-ops": [ 42 | 2 43 | ], 44 | "object-curly-spacing": [ 45 | "error", 46 | "always" 47 | ], 48 | "semi": [ 49 | "error", 50 | "always" 51 | ], 52 | "indent": [ 53 | 2, 54 | 4 55 | ], 56 | "quotes": [ 57 | 0, 58 | "single" 59 | ], 60 | "space-before-blocks": [ 61 | 0, 62 | "always" 63 | ], 64 | "eqeqeq": 0, 65 | "no-case-declarations": 0, 66 | "no-eval": 0, 67 | "no-useless-escape": 0, 68 | "valid-jsdoc": 0, 69 | "valid-typeof": 2, 70 | "id-match": 0, 71 | "no-async-promise-executor": 0, 72 | "max-depth": [ 73 | 0, 74 | 4 75 | ], 76 | "max-len": [ 77 | 0, 78 | 80, 79 | 4 80 | ], 81 | "max-nested-callbacks": [ 82 | 0, 83 | 2 84 | ], 85 | "complexity": [ 86 | 0, 87 | 11 88 | ], 89 | "camelcase": 0, 90 | "constructor-super": 0, 91 | "no-duplicate-case": 2, 92 | "no-fallthrough": 2, 93 | "no-unreachable": 2, 94 | "no-unused-vars": [ 95 | 0, 96 | { 97 | "vars": "all", 98 | "args": "none" 99 | } 100 | ] 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /src/components/Map/CesiumView.vue: -------------------------------------------------------------------------------- 1 | 5 | 6 | 61 | 62 | 72 | -------------------------------------------------------------------------------- /src/router/index.ts: -------------------------------------------------------------------------------- 1 | import Vue from 'vue'; 2 | import VueRouter, { RawLocation } from 'vue-router'; 3 | 4 | Vue.use(VueRouter); 5 | const originalPush = VueRouter.prototype.push; 6 | VueRouter.prototype.push = function push(location: RawLocation) { 7 | // @ts-ignore 8 | return originalPush.call(this, location).catch((err: any) => err); 9 | }; 10 | export const router: VueRouter = new VueRouter({ 11 | mode: 'hash', 12 | routes: [ 13 | { 14 | path: '/', 15 | redirect: { 16 | path: '/baseManage/marker' 17 | } 18 | }, 19 | { 20 | path: '/baseManage/marker', 21 | component: () => import('../views/baseManage/MarkerPage.vue'), 22 | }, 23 | { 24 | path: '/baseManage/line', 25 | component: () => import('../views/baseManage/LinePage.vue'), 26 | }, 27 | { 28 | path: '/baseManage/popUp', 29 | component: () => import('../views/baseManage/PopUpPage.vue'), 30 | }, 31 | { 32 | path: '/baseManage/cover', 33 | component: () => import('../views/baseManage/CoverPage.vue'), 34 | }, 35 | { 36 | path: '/dataManage/interpolation', 37 | name: '插值', 38 | component: () => import('../views/dataManage/Interpolation.vue'), 39 | }, 40 | { 41 | path: '/dataManage/migrationMapPage', 42 | name: '迁徙图', 43 | component: () => import('../views/dataManage/MigrationMapPage.vue'), 44 | }, 45 | { 46 | path: '/dataManage/windFieldPage', 47 | name: '风场', 48 | component: () => import('../views/dataManage/WindFieldPage.vue'), 49 | }, 50 | { 51 | path: '/modelManage/cesiumBaseModel', 52 | name: 'cesium基本模型', 53 | component: () => import('../views/modelManage/CesiumBaseModel.vue'), 54 | }, 55 | { 56 | path: '/modelManage/mapBoxBaseModel', 57 | name: 'mapbox基本模型', 58 | component: () => import('../views/modelManage/MapBoxBaseModel.vue'), 59 | }, 60 | { 61 | path: '/modelManage/mapBoxCityModel', 62 | name: 'mapbox城市模型', 63 | component: () => import('../views/modelManage/MapBoxCityModel.vue'), 64 | }, 65 | { 66 | path: '/modelManage/cesiumCityModel', 67 | name: 'cesium城市模型', 68 | component: () => import('../views/modelManage/CesiumCityModel.vue'), 69 | } 70 | 71 | ] 72 | }); 73 | -------------------------------------------------------------------------------- /src/components/dialog/marker/LeafletMarkerDialog.vue: -------------------------------------------------------------------------------- 1 | 22 | 23 | 61 | 62 | 91 | -------------------------------------------------------------------------------- /src/components/dialog/marker/MapboxMarkerDialog.vue: -------------------------------------------------------------------------------- 1 | 21 | 22 | 61 | 62 | 92 | -------------------------------------------------------------------------------- /src/components/layouts/SettingLayout.vue: -------------------------------------------------------------------------------- 1 | 22 | 23 | 61 | 62 | 84 | -------------------------------------------------------------------------------- /src/components/dialog/marker/CesiumMarkerDialog.vue: -------------------------------------------------------------------------------- 1 | 22 | 23 | 61 | 62 | 91 | -------------------------------------------------------------------------------- /src/map/service/leaflet/imageryProvider/TileLayerBaidu.ts: -------------------------------------------------------------------------------- 1 | import L from 'leaflet'; 2 | import 'proj4/projs'; 3 | import 'proj4leaflet/src/proj4leaflet'; 4 | 5 | (L.CRS as any).Baidu = new (L as any).Proj.CRS('EPSG:900913', '+proj=merc +a=6378206 +b=6356584.314245179 +lat_ts=0.0 +lon_0=0.0 +x_0=0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs', { 6 | resolutions: function () { 7 | let level: number = 19; 8 | const res: any = []; 9 | res[0] = Math.pow(2, 18); 10 | for (let i = 1; i < level; i++) { 11 | res[i] = Math.pow(2, (18 - i)); 12 | } 13 | return res; 14 | }(), 15 | origin: [0, 0], 16 | bounds: L.bounds([20037508.342789244, 0], [0, 20037508.342789244]) 17 | }); 18 | 19 | (L.tileLayer as any).baidu = function (option: any) { 20 | option = option || {}; 21 | 22 | let layer: any; 23 | let subdomains = '0123456789'; 24 | const time = new Date().getTime(); 25 | switch (option.layer) { 26 | //单图层 27 | case "vec": 28 | default: 29 | // @ts-ignore 30 | layer = L.tileLayer('http://online{s}.map.bdimg.com/onlinelabel/?qt=tile&x={x}&y={y}&z={z}&styles=' + (option.bigfont ? 'ph' : 'pl') + '&scaler=1&p=1', { name: option.name, subdomains: subdomains, tms: true }); 31 | break; 32 | case "img_d": 33 | // @ts-ignore 34 | layer = L.tileLayer('http://shangetu{s}.map.bdimg.com/it/u=x={x};y={y};z={z};v=009;type=sate&fm=46', { name: option.name, subdomains: subdomains, tms: true }); 35 | break; 36 | case "img_z": 37 | // @ts-ignore 38 | layer = L.tileLayer('http://online{s}.map.bdimg.com/tile/?qt=tile&x={x}&y={y}&z={z}&styles=' + (option.bigfont ? 'sh' : 'sl') + '&v=020', { name: option.name, subdomains: subdomains, tms: true }); 39 | break; 40 | 41 | case "custom"://Custom 各种自定义样式 42 | //可选值:dark,midnight,grayscale,hardedge,light,redalert,googlelite,grassgreen,pink,darkgreen,bluish 43 | option.customid = option.customid || 'midnight'; 44 | // @ts-ignore 45 | layer = L.tileLayer('http://api{s}.map.bdimg.com/customimage/tile?&x={x}&y={y}&z={z}&scale=1&customid=' + option.customid, { name: option.name, subdomains: "012", tms: true }); 46 | break; 47 | 48 | case "time"://实时路况 49 | // @ts-ignore 50 | layer = L.tileLayer('http://its.map.baidu.com:8002/traffic/TrafficTileService?x={x}&y={y}&level={z}&time=' + time + '&label=web2D&v=017', { name: option.name, subdomains: subdomains, tms: true }); 51 | break; 52 | 53 | //合并 54 | case "img": 55 | layer = L.layerGroup([ 56 | (L.tileLayer as any).baidu({ name: "底图", layer: 'img_d', bigfont: option.bigfont }), 57 | (L.tileLayer as any).baidu({ name: "注记", layer: 'img_z', bigfont: option.bigfont }) 58 | ]); 59 | break; 60 | } 61 | return layer; 62 | }; 63 | -------------------------------------------------------------------------------- /src/map/service/cesium/plugin/echarts/RegisterCoordinateSystem.ts: -------------------------------------------------------------------------------- 1 | // @ts-nocheck 2 | import echarts from "echarts"; 3 | import { Cartesian3, Math, SceneMode } from 'cesium'; 4 | 5 | class RegisterCoordinateSystem { 6 | dimensions = ["lng", "lat"] 7 | radians = Math.toRadians(80) 8 | private _GLMap: any; 9 | private _mapOffset: any; 10 | constructor(glMap) { 11 | this._GLMap = glMap; 12 | this._mapOffset = [0, 0]; 13 | this.dimensions = ['lng', 'lat']; 14 | //this._api = api; 15 | } 16 | 17 | setMapOffset(mapOffset) { 18 | this._mapOffset = mapOffset; 19 | } 20 | 21 | getMap() { 22 | return this._GLMap; 23 | } 24 | 25 | fixLat(lat) { 26 | return lat >= 90 ? 89.99999999999999 : lat <= -90 ? -89.99999999999999 : lat; 27 | } 28 | 29 | dataToPoint(coords) { 30 | let lonlat = [99999, 99999]; 31 | coords[1] = this.fixLat(coords[1]); 32 | let position = Cartesian3.fromDegrees(coords[0], coords[1]); 33 | if (!position) return lonlat; 34 | let coordinates = this._GLMap.cartesianToCanvasCoordinates(position); 35 | if (!coordinates) return lonlat; 36 | if (this._GLMap.mode === SceneMode.SCENE3D) { 37 | if (Cartesian3.angleBetween(this._GLMap.camera.position, position) > this.radians) return !1; 38 | } 39 | return [coordinates.x - this._mapOffset[0], coordinates.y - this._mapOffset[1]]; 40 | } 41 | 42 | pointToData(pixel) { 43 | let mapOffset = this._mapOffset, 44 | coords = this._bmap.project([pixel[0] + pixel[0], pixel[1] + pixel[1]]); 45 | return [coords.lng, coords.lat]; 46 | } 47 | 48 | getViewRect() { 49 | let api = this._api; 50 | return new echarts.graphic.BoundingRect(0, 0, api.getWidth(), api.getHeight()); 51 | } 52 | 53 | getRoamTransform() { 54 | return echarts.matrix.create(); 55 | } 56 | 57 | create(echartModel, api) { 58 | this._api = api; 59 | let registerCoordinateSystem; 60 | echartModel.eachComponent("GLMap", function(seriesModel) { 61 | let painter = api.getZr().painter; 62 | if (painter) { 63 | //let glMap = (api.getViewportRoot(), echarts.glMap); 64 | let glMap = echarts.glMap; 65 | registerCoordinateSystem = new RegisterCoordinateSystem(glMap, api); 66 | registerCoordinateSystem.setMapOffset(seriesModel.__mapOffset || [0, 0]); 67 | seriesModel.coordinateSystem = registerCoordinateSystem; 68 | } 69 | }); 70 | 71 | echartModel.eachSeries(function(series) { 72 | "GLMap" === series.get("coordinateSystem") && (series.coordinateSystem = registerCoordinateSystem); 73 | }); 74 | } 75 | 76 | } 77 | 78 | export default RegisterCoordinateSystem; 79 | // @ts-check 80 | -------------------------------------------------------------------------------- /src/components/dialog/cover/MapboxCoverDialog.vue: -------------------------------------------------------------------------------- 1 | 23 | 24 | 65 | 66 | 95 | -------------------------------------------------------------------------------- /src/components/dialog/line/CesiumLineDialog.vue: -------------------------------------------------------------------------------- 1 | 23 | 24 | 65 | 66 | 95 | -------------------------------------------------------------------------------- /src/components/dialog/line/LeafletLineDialog.vue: -------------------------------------------------------------------------------- 1 | 23 | 24 | 65 | 66 | 95 | -------------------------------------------------------------------------------- /src/components/dialog/line/MapboxLineDialog.vue: -------------------------------------------------------------------------------- 1 | 23 | 24 | 65 | 66 | 95 | -------------------------------------------------------------------------------- /src/components/dialog/cover/CesiumCoverDialog.vue: -------------------------------------------------------------------------------- 1 | 23 | 24 | 65 | 66 | 95 | -------------------------------------------------------------------------------- /src/components/dialog/cover/LeafletCoverDialog.vue: -------------------------------------------------------------------------------- 1 | 23 | 24 | 65 | 66 | 95 | -------------------------------------------------------------------------------- /src/components/dialog/interpolation/InterpolationDialog.vue: -------------------------------------------------------------------------------- 1 | 22 | 23 | 66 | 67 | 96 | -------------------------------------------------------------------------------- /src/map/service/cesium/widgets/CesiumCustomPopUp.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @author fei_yong 3 | * @since 2021-07-11 9:39 4 | * @desc cesium 自定义弹框 5 | */ 6 | import { Cartesian2, Event, SceneTransforms, Viewer } from 'cesium'; 7 | 8 | interface CesiumCustomPopUpOption { 9 | viewer: Viewer; // 地图实例 10 | $sel: HTMLElement; 11 | position: any; 12 | windowCloseCallback?: () => void; 13 | } 14 | export class CesiumCustomPopUp { 15 | 16 | private viewer: Viewer; 17 | 18 | private $sel: HTMLElement; 19 | 20 | private position: any; 21 | 22 | private windowCloseCallback: () => void; 23 | 24 | private removeListener: Event.RemoveCallback; 25 | 26 | constructor(options: CesiumCustomPopUpOption) { 27 | this.init(options); 28 | } 29 | 30 | /** 31 | * 組件初始化 32 | * @param options 33 | * @private 34 | */ 35 | private init(options: CesiumCustomPopUpOption) { 36 | this.viewer = options.viewer; 37 | this.$sel = options.$sel; 38 | this.position = options.position; 39 | if (options.windowCloseCallback && typeof options.windowCloseCallback === 'function') { 40 | this.windowCloseCallback = options.windowCloseCallback; 41 | } 42 | this.viewer.cesiumWidget.container.appendChild(this.$sel); //将字符串模板生成的内容添加到DOM上 43 | this.addPostRender(); 44 | 45 | } 46 | 47 | /** 48 | * 關閉彈框 49 | */ 50 | public destroy() { 51 | try { 52 | if (this.windowCloseCallback && typeof this.windowCloseCallback === 'function') { 53 | this.windowCloseCallback(); 54 | } 55 | // 移除弹框内容 56 | this.viewer.cesiumWidget.container.removeChild(this.$sel); 57 | if (this.removeListener) { 58 | this.removeListener(); 59 | } 60 | // 移除事件监听 61 | // this.viewer.scene.postRender.removeEventListener(this.postRender, this); 62 | }catch (e) { 63 | console.log(e); 64 | } 65 | 66 | } 67 | 68 | /** 69 | * 事件绑定 70 | */ 71 | public addPostRender() { 72 | this.removeListener = this.viewer.scene.postRender.addEventListener(this.postRender, this); 73 | } 74 | 75 | /** 76 | * 定位、样式处理 77 | */ 78 | public postRender() { 79 | if (!this.$sel || !this.$sel.style) return; 80 | const canvasHeight = this.viewer.scene.canvas.height; 81 | const windowPosition = new Cartesian2(); 82 | SceneTransforms.wgs84ToWindowCoordinates(this.viewer.scene, this.position, windowPosition); 83 | this.$sel.style.bottom = canvasHeight - windowPosition.y + 40 + "px"; 84 | const elWidth: number = this.$sel.offsetWidth; 85 | this.$sel.style.left = windowPosition.x - (elWidth / 2) + "px"; 86 | 87 | // TODO 此处逻辑有问题,暂时屏蔽掉 88 | 89 | // if (this.viewer.camera.positionCartographic.height > 4000) { 90 | // this.$sel.style.display = "none"; 91 | // } else { 92 | // this.$sel.style.display = "block"; 93 | // } 94 | } 95 | 96 | 97 | } 98 | -------------------------------------------------------------------------------- /src/data/gltf/house.gltf: -------------------------------------------------------------------------------- 1 | {"accessors":[{"name":"object_1_1_positions","componentType":5126,"count":42,"min":[-6,0,-3],"max":[6,11,3],"type":"VEC3","bufferView":0,"byteOffset":0},{"name":"object_1_1_normals","componentType":5126,"count":42,"min":[-1,-1,-1],"max":[1,0.70710676908493,1],"type":"VEC3","bufferView":0,"byteOffset":504},{"name":"object_1_1_texcoords","componentType":5126,"count":42,"min":[0,0],"max":[1,1],"type":"VEC2","bufferView":1,"byteOffset":0},{"name":"object_1_1_0_indices","componentType":5123,"count":72,"min":[0],"max":[41],"type":"SCALAR","bufferView":2,"byteOffset":0}],"asset":{"generator":"obj2gltf","version":"2.0"},"buffers":[{"name":"fangzi","byteLength":1488,"uri":"data:application\/octet-stream;base64,AAAAAAAAMEEAAEBAAADAQAAAoEAAAEBAAADAQAAAoEAAAEDAAAAAAAAAMEEAAEDAAADAQAAAoEAAAEBAAACAQAAAoEAAAEBAAACAQAAAoEAAAEDAAADAQAAAoEAAAEDAAACAQAAAoEAAAEBAAACAQAAAAAAAAEBAAACAQAAAAAAAAEDAAACAQAAAoEAAAEDAAACAQAAAAAAAAEBAAACAwAAAAAAAAEBAAACAwAAAAAAAAEDAAACAQAAAAAAAAEDAAACAwAAAAAAAAEBAAACAwAAAoEAAAEBAAACAwAAAoEAAAEDAAACAwAAAAAAAAEDAAACAwAAAoEAAAEBAAADAwAAAoEAAAEBAAADAwAAAoEAAAEDAAACAwAAAoEAAAEDAAADAwAAAoEAAAEBAAAAAAAAAMEEAAEBAAAAAAAAAMEEAAEDAAADAwAAAoEAAAEDAAACAwAAAAAAAAEBAAACAQAAAAAAAAEBAAACAQAAAoEAAAEBAAAAAAAAAMEEAAEBAAADAQAAAoEAAAEBAAACAwAAAoEAAAEBAAADAwAAAoEAAAEBAAACAwAAAAAAAAEDAAACAQAAAoEAAAEDAAACAQAAAAAAAAEDAAAAAAAAAMEEAAEDAAADAQAAAoEAAAEDAAACAwAAAoEAAAEDAAADAwAAAoEAAAEDA8wQ1P\/MENT8AAAAA8wQ1P\/MENT8AAAAA8wQ1P\/MENT8AAAAA8wQ1P\/MENT8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAA8wQ1v\/MENT8AAAAA8wQ1v\/MENT8AAAAA8wQ1v\/MENT8AAAAA8wQ1v\/MENT8AAAAAAAAAAAAAAAAAAIA\/AAAAAAAAAAAAAIA\/AAAAAAAAAAAAAIA\/AAAAAAAAAAAAAIA\/AAAAAAAAAAAAAIA\/AAAAAAAAAAAAAIA\/AAAAAAAAAAAAAIA\/AAAAAAAAAAAAAIC\/AAAAAAAAAAAAAIC\/AAAAAAAAAAAAAIC\/AAAAAAAAAAAAAIC\/AAAAAAAAAAAAAIC\/AAAAAAAAAAAAAIC\/AAAAAAAAAAAAAIC\/AAAAAAAAgD8Z9l4+AACAPxn2Xj6eJMk+AAAAAJ4kyT4Z9l4+AACAP8TBiT4AAIA\/xMGJPp4kyT4Z9l4+niTJPsTBiT4AAIA\/kHLLPgAAgD+Qcss+niTJPsTBiT6eJMk+kHLLPgAAgD+4Rho\/AACAP7hGGj+eJMk+kHLLPp4kyT64Rho\/AACAPx4fOz8AAIA\/Hh87P54kyT64Rho\/niTJPh4fOz8AAIA\/ekJIPwAAgD96Qkg\/niTJPh4fOz+eJMk+ekJIPwAAgD8AAIA\/AACAPwAAgD+eJMk+ekJIP54kyT6YYYM+AAAAAL81Uj0AAAAAvzVSPWjbNj5PqB0+iiTJPgAAAABo2zY+mGGDPmjbNj5PqJ0+aNs2Pphhgz6KJMk+vzVSPbBtWz6\/NVI9iiTJPk+oHT4AAAAAAAAAALBtWz6YYYM+sG1bPk+onT6wbVs+AAABAAIAAAACAAMABAAFAAYABAAGAAcACAAJAAoACAAKAAsADAANAA4ADAAOAA8AEAARABIAEAASABMAFAAVABYAFAAWABcAGAAZABoAGAAaABsAHAAdAB4AHwAeACAAHgAfACEAIQAfACIAHAAeACEAIwAkACUAJgAnACQAJAAoACYAKAApACYAIwAoACQA"}],"bufferViews":[{"name":"bufferView_0","buffer":0,"byteLength":1008,"byteOffset":0,"byteStride":12,"target":34962},{"name":"bufferView_1","buffer":0,"byteLength":336,"byteOffset":1008,"byteStride":8,"target":34962},{"name":"bufferView_2","buffer":0,"byteLength":144,"byteOffset":1344,"target":34963}],"materials":[{"name":"Default","pbrMetallicRoughness":{"baseColorFactor":[1,1,1,1],"metallicFactor":0,"roughnessFactor":1},"emissiveFactor":[0,0,0],"alphaMode":"OPAQUE","doubleSided":false}],"meshes":[{"name":"object_1_1","primitives":[{"attributes":{"POSITION":0,"NORMAL":1,"TEXCOORD_0":2},"indices":3,"material":0,"mode":4}]}],"nodes":[{"name":"object_1","mesh":0}],"scene":0,"scenes":[{"nodes":[0]}]} -------------------------------------------------------------------------------- /src/components/dialog/migrationMap/MigrationMapDialog.vue: -------------------------------------------------------------------------------- 1 | 23 | 24 | 72 | 73 | 102 | -------------------------------------------------------------------------------- /src/map/common/pugin/echartslayer-libs/dist/EchartsLayer.min.js: -------------------------------------------------------------------------------- 1 | !function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e(require("echarts")):"function"==typeof define&&define.amd?define(["echarts"],e):"object"==typeof exports?exports.EchartsLayer=e(require("echarts")):t.EchartsLayer=e(t.echarts)}(this,function(t){return function(t){function e(n){if(o[n])return o[n].exports;var i=o[n]={exports:{},id:n,loaded:!1};return t[n].call(i.exports,i,i.exports,e),i.loaded=!0,i.exports}var o={};return e.m=t,e.c=o,e.p="",e(0)}([function(t,e,o){o(3);var n=o(2);t.exports=n},function(e,o){e.exports=t},function(t,e){function o(t){const e=t.getCanvasContainer();this._container=document.createElement("div"),this._container.style.width=t.getCanvas().style.width,this._container.style.height=t.getCanvas().style.height,this._container.setAttribute("id","echarts"),this._container.setAttribute("class","echartMap"),this._map=t,e.appendChild(this._container),this.chart=echarts.init(this._container),echarts.glMap=t,this.resize()}o.prototype.remove=function(){var t=this;this._map._listeners.move.forEach(function(e){"moveHandler"===e.name&&t._map.off("move",e)}),this._map._listeners.move.forEach(function(e){"zoomEndHandler"===e.name&&t._map.off("zoomend",e)}),this.chart.clear(),this._container.parentNode&&this._container.parentNode.removeChild(this._container),this._map=void 0},o.prototype.resize=function(){const t=this;window.onresize=function(){t._container.style.width=t._map.getCanvas().style.width,t._container.style.height=t._map.getCanvas().style.height,t.chart.resize()}},t.exports=o},function(t,e,o){var n;n=function(t){return o(1).registerCoordinateSystem("GLMap",o(4)),o(5),o(6),o(1).registerAction({type:"GLMapRoam",event:"GLMapRoam",update:"updateLayout"},function(t,e){}),{version:"1.0.0"}}.call(e,o,e,t),!(void 0!==n&&(t.exports=n))},function(t,e,o){var n;n=function(t){function e(t,e){this._GLMap=t,this.dimensions=["lng","lat"],this._mapOffset=[0,0],this._api=e}var n=o(1);return e.prototype.dimensions=["lng","lat"],e.prototype.setMapOffset=function(t){this._mapOffset=t},e.prototype.getBMap=function(){return this._GLMap},e.prototype.dataToPoint=function(t){var e=this._GLMap.project(t),o=this._mapOffset;return[e.x-o[0],e.y-o[1]]},e.prototype.pointToData=function(t){var e=this._mapOffset,t=this._bmap.project([t[0]+e[0],t[1]+e[1]]);return[t.lng,t.lat]},e.prototype.getViewRect=function(){var t=this._api;return new n.graphic.BoundingRect(0,0,t.getWidth(),t.getHeight())},e.prototype.getRoamTransform=function(){return n.matrix.create()},e.dimensions=e.prototype.dimensions,e.create=function(t,o){var i;t.eachComponent("GLMap",function(t){var a=(o.getZr().painter.getViewportRoot(),n.glMap);i=new e(a,o),i.setMapOffset(t.__mapOffset||[0,0]),t.coordinateSystem=i}),t.eachSeries(function(t){"GLMap"===t.get("coordinateSystem")&&(t.coordinateSystem=i)})},e}.call(e,o,e,t),!(void 0!==n&&(t.exports=n))},function(t,e,o){var n;n=function(t){return o(1).extendComponentModel({type:"GLMap",getBMap:function(){return this.__GLMap},defaultOption:{roam:!1}})}.call(e,o,e,t),!(void 0!==n&&(t.exports=n))},function(t,e,o){var n;n=function(t){return o(1).extendComponentView({type:"GLMap",render:function(t,e,o){function n(){i||o.dispatchAction({type:"GLMapRoam"})}var i=!0,a=echarts.glMap,r=o.getZr().painter.getViewportRoot(),s=t.coordinateSystem,p=function(e,n){if(!i){var a=document.getElementsByClassName("mapboxgl-map")[0],p=[-parseInt(a.style.left,10)||0,-parseInt(a.style.top,10)||0];r.style.left=p[0]+"px",r.style.top=p[1]+"px",s.setMapOffset(p),t.__mapOffset=p,o.dispatchAction({type:"GLMapRoam"})}};a.off("move",this._oldMoveHandler),a.off("zoomend",this._oldZoomEndHandler),a.on("move",p),a.on("zoomend",n),this._oldMoveHandler=p,this._oldZoomEndHandler=n;t.get("roam");i=!1}})}.call(e,o,e,t),!(void 0!==n&&(t.exports=n))}])}); -------------------------------------------------------------------------------- /src/map/service/mapbox/pugin/echartslayer-libs/dist/EchartsLayer.min.js: -------------------------------------------------------------------------------- 1 | !function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e(require("echarts")):"function"==typeof define&&define.amd?define(["echarts"],e):"object"==typeof exports?exports.EchartsLayer=e(require("echarts")):t.EchartsLayer=e(t.echarts)}(this,function(t){return function(t){function e(n){if(o[n])return o[n].exports;var i=o[n]={exports:{},id:n,loaded:!1};return t[n].call(i.exports,i,i.exports,e),i.loaded=!0,i.exports}var o={};return e.m=t,e.c=o,e.p="",e(0)}([function(t,e,o){o(3);var n=o(2);t.exports=n},function(e,o){e.exports=t},function(t,e){function o(t){const e=t.getCanvasContainer();this._container=document.createElement("div"),this._container.style.width=t.getCanvas().style.width,this._container.style.height=t.getCanvas().style.height,this._container.setAttribute("id","echarts"),this._container.setAttribute("class","echartMap"),this._map=t,e.appendChild(this._container),this.chart=echarts.init(this._container),echarts.glMap=t,this.resize()}o.prototype.remove=function(){var t=this;this._map._listeners.move.forEach(function(e){"moveHandler"===e.name&&t._map.off("move",e)}),this._map._listeners.move.forEach(function(e){"zoomEndHandler"===e.name&&t._map.off("zoomend",e)}),this.chart.clear(),this._container.parentNode&&this._container.parentNode.removeChild(this._container),this._map=void 0},o.prototype.resize=function(){const t=this;window.onresize=function(){t._container.style.width=t._map.getCanvas().style.width,t._container.style.height=t._map.getCanvas().style.height,t.chart.resize()}},t.exports=o},function(t,e,o){var n;n=function(t){return o(1).registerCoordinateSystem("GLMap",o(4)),o(5),o(6),o(1).registerAction({type:"GLMapRoam",event:"GLMapRoam",update:"updateLayout"},function(t,e){}),{version:"1.0.0"}}.call(e,o,e,t),!(void 0!==n&&(t.exports=n))},function(t,e,o){var n;n=function(t){function e(t,e){this._GLMap=t,this.dimensions=["lng","lat"],this._mapOffset=[0,0],this._api=e}var n=o(1);return e.prototype.dimensions=["lng","lat"],e.prototype.setMapOffset=function(t){this._mapOffset=t},e.prototype.getBMap=function(){return this._GLMap},e.prototype.dataToPoint=function(t){var e=this._GLMap.project(t),o=this._mapOffset;return[e.x-o[0],e.y-o[1]]},e.prototype.pointToData=function(t){var e=this._mapOffset,t=this._bmap.project([t[0]+e[0],t[1]+e[1]]);return[t.lng,t.lat]},e.prototype.getViewRect=function(){var t=this._api;return new n.graphic.BoundingRect(0,0,t.getWidth(),t.getHeight())},e.prototype.getRoamTransform=function(){return n.matrix.create()},e.dimensions=e.prototype.dimensions,e.create=function(t,o){var i;t.eachComponent("GLMap",function(t){var a=(o.getZr().painter.getViewportRoot(),n.glMap);i=new e(a,o),i.setMapOffset(t.__mapOffset||[0,0]),t.coordinateSystem=i}),t.eachSeries(function(t){"GLMap"===t.get("coordinateSystem")&&(t.coordinateSystem=i)})},e}.call(e,o,e,t),!(void 0!==n&&(t.exports=n))},function(t,e,o){var n;n=function(t){return o(1).extendComponentModel({type:"GLMap",getBMap:function(){return this.__GLMap},defaultOption:{roam:!1}})}.call(e,o,e,t),!(void 0!==n&&(t.exports=n))},function(t,e,o){var n;n=function(t){return o(1).extendComponentView({type:"GLMap",render:function(t,e,o){function n(){i||o.dispatchAction({type:"GLMapRoam"})}var i=!0,a=echarts.glMap,r=o.getZr().painter.getViewportRoot(),s=t.coordinateSystem,p=function(e,n){if(!i){var a=document.getElementsByClassName("mapboxgl-map")[0],p=[-parseInt(a.style.left,10)||0,-parseInt(a.style.top,10)||0];r.style.left=p[0]+"px",r.style.top=p[1]+"px",s.setMapOffset(p),t.__mapOffset=p,o.dispatchAction({type:"GLMapRoam"})}};a.off("move",this._oldMoveHandler),a.off("zoomend",this._oldZoomEndHandler),a.on("move",p),a.on("zoomend",n),this._oldMoveHandler=p,this._oldZoomEndHandler=n;t.get("roam");i=!1}})}.call(e,o,e,t),!(void 0!==n&&(t.exports=n))}])}); -------------------------------------------------------------------------------- /src/data/gltf/pyramid.gltf: -------------------------------------------------------------------------------- 1 | {"accessors":[{"name":"object_1_1_positions","componentType":5126,"count":48,"min":[-4.4116382598877,0,-4.4222602844238],"max":[4,7,3.9691751003265],"type":"VEC3","bufferView":0,"byteOffset":0},{"name":"object_1_1_normals","componentType":5126,"count":48,"min":[-0.79456895589828,-1,-0.78844583034515],"max":[0.87633776664734,0.45915701985359,0.8784476518631],"type":"VEC3","bufferView":0,"byteOffset":576},{"name":"object_1_1_texcoords","componentType":5126,"count":48,"min":[0,0.11622947454453],"max":[0.99853515625,1],"type":"VEC2","bufferView":1,"byteOffset":0},{"name":"object_1_1_0_indices","componentType":5123,"count":108,"min":[0],"max":[47],"type":"SCALAR","bufferView":2,"byteOffset":0}],"asset":{"generator":"obj2gltf","version":"2.0"},"buffers":[{"name":"building_Pyramid","byteLength":1752,"uri":"data:application\/octet-stream;base64,q6oqQFVVFUCrqqq\/6FdjvlVVlUDfrry\/q6qqP1VVlUCrqiq\/AAAAAAAA4EAAAAAAhV\/VPwAAAAAog03AAACAQAAAAAAAAADA6FfjvlVVFUDfrjzA7oEqvwAAAAAog43A6FfjvlVVFUDfrjzA7oEqvwAAAAAog43AYnwiwAAAAADE+CTA2zo8wFVVFUDeO\/q+6FdjvlVVlUDfrry\/2zq8v1VVlUDeO3q+AAAAAAAA4EAAAAAAJCyNwAAAAADnrDu\/2zq8v1VVlUDeO3q+2zo8wFVVFUDeO\/q+QdQvv1VVlUD6Wak\/QdSvv1VVFUD6WSlAJCyNwAAAAADnrDu\/Md8DwAAAAAD3Bn5AAAAAAAAA4EAAAAAAQdSvv1VVFUD6WSlAMd8DwAAAAAD3Bn5AifEJPwAAAADE+GRATuUFQFVVFUC38QdATuWFP1VVlUC38Yc\/QdQvv1VVlUD6Wak\/9ddIQAAAAACS6ktAAAAAAAAA4EAAAAAAq6oqQFVVFUCrqqq\/TuWFP1VVlUC38Yc\/TuUFQFVVFUC38QdAq6qqP1VVlUCrqiq\/AAAAAAAA4EAAAAAA9ddIQAAAAACS6ktA+2tkQAAAAAAk1Rc\/AACAQAAAAAAAAADAJCyNwAAAAADnrDu\/ifEJPwAAAADE+GRAMd8DwAAAAAD3Bn5AYnwiwAAAAADE+CTA+2tkQAAAAAAk1Rc\/hV\/VPwAAAAAog03A7oEqvwAAAAAog43AAACAQAAAAAAAAADA9ddIQAAAAACS6ktAA5DRPqEW6z6W10m\/A5DRPqEW6z6W10m\/A5DRPqEW6z6W10m\/A5DRPqEW6z6W10m\/A5DRPqEW6z6W10m\/A5DRPqEW6z6W10m\/A5DRPqEW6z6W10m\/A5DRPqEW6z6W10m\/hpUfv6EW6z6LBiK\/hpUfv6EW6z6LBiK\/hpUfv6EW6z6LBiK\/hpUfv6EW6z6LBiK\/hpUfv6EW6z6LBiK\/hpUfv6EW6z6LBiK\/hpUfv6EW6z6LBiK\/hpUfv6EW6z6LBiK\/32hLv6EW6z7faMs+32hLv6EW6z7faMs+32hLv6EW6z7faMs+32hLv6EW6z7faMs+32hLv6EW6z7faMs+32hLv6EW6z7faMs+32hLv6EW6z7faMs+4XoHPqEW6z7y4WA\/4XoHPqEW6z7y4WA\/4XoHPqEW6z7y4WA\/4XoHPqEW6z7y4WA\/4XoHPqEW6z7y4WA\/4XoHPqEW6z7y4WA\/4XoHPqEW6z7y4WA\/4XoHPqEW6z7y4WA\/rFdgP6EW6z79HhU+rFdgP6EW6z79HhU+rFdgP6EW6z79HhU+rFdgP6EW6z79HhU+rFdgP6EW6z79HhU+rFdgP6EW6z79HhU+rFdgP6EW6z79HhU+rFdgP6EW6z79HhU+AAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAl8QpPY7s+j6XxCk+zO+6PpfEqT3M77o+46b+PRDmdT7jpv49qHQdPwAAAACodB0\/vTVUPo7s+j7jpn4+qHQdP\/aM\/z5e2BI\/3KQfP6h0HT\/cpB8\/mD\/7PvaM\/z5yztA+NNC\/PhU8CD800L8+BAfmPnETgD6YP\/s+3KQfP96Vuz494z8\/badqP5\/BXz+3U3U\/PeM\/P9pOVT+fwV8\/kaJKPwCgfz8AAIA\/AKB\/P0j2Pz\/cBCA\/JPtfP\/aM\/z5MnaU+3KQfP97Vuj7cpB8\/TFh2PvaM\/z4AdiE+NNC\/PijnSz400L8+umSQPtykHz+4Ce49cROAPkxYdj6fwV8\/WKayPj3jPz8QsPI+n8FfP1IEBD894z8\/7P7HPtwEID9+V90+AKB\/P5ywDj8AoH8\/flfdPgCgfz\/GTZ0+gk+ePQAAgD9Ccbs+\/alhP1Knpz4AAIA\/hU8ePf2pYT9mbJs+UZQwPzI7zz1RlDA\/AAAAAPpTQz8yO08+qNQdPzI7zz76U0M\/AAABAAIAAgABAAMABAAAAAUABgAEAAcABgABAAAABAAGAAAACAAJAAoACAALAAwACwAIAAoACwANAAwADQAOAAwADwALAAoAEAARABIAEwARABQAEwAUABUAEQATABIAEgAWABAAFwAYABkAFwAaABsAFwAbABwAGgAXABkAGgAZAB0AGwAeABwAHwAgACEAIAAiACMAJAAlACEAHwAlACYAHwAiACAAJQAfACEAJwAoACkAKAAnACoAKgArACgAKwAqACwAKgAtACwALgArACwALwAoACsA"}],"bufferViews":[{"name":"bufferView_0","buffer":0,"byteLength":1152,"byteOffset":0,"byteStride":12,"target":34962},{"name":"bufferView_1","buffer":0,"byteLength":384,"byteOffset":1152,"byteStride":8,"target":34962},{"name":"bufferView_2","buffer":0,"byteLength":216,"byteOffset":1536,"target":34963}],"materials":[{"name":"Default","pbrMetallicRoughness":{"baseColorFactor":[1,1,1,1],"metallicFactor":0,"roughnessFactor":1},"emissiveFactor":[0,0,0],"alphaMode":"OPAQUE","doubleSided":false}],"meshes":[{"name":"object_1_1","primitives":[{"attributes":{"POSITION":0,"NORMAL":1,"TEXCOORD_0":2},"indices":3,"material":0,"mode":4}]}],"nodes":[{"name":"object_1","mesh":0}],"scene":0,"scenes":[{"nodes":[0]}]} -------------------------------------------------------------------------------- /src/map/service/cesium/plugin/echarts/EchartsLayer.ts: -------------------------------------------------------------------------------- 1 | // @ts-nocheck 2 | import echarts from "echarts"; 3 | import RegisterCoordinateSystem from "./RegisterCoordinateSystem"; 4 | 5 | export class EchartsLayer { 6 | private _chartLayer: echarts.ECharts; 7 | private readonly _viewer: any; 8 | private option: any; 9 | private _isRegistered: boolean; 10 | private _echartsContainer: any; 11 | constructor(viewer: any, option: any) { 12 | this._viewer = viewer; 13 | this._isRegistered = false; 14 | this._chartLayer = this._createLayerContainer(); 15 | this.option = option; 16 | this._chartLayer.setOption(option); 17 | } 18 | 19 | _createLayerContainer() { 20 | const scene: any = this._viewer.scene; 21 | const container: any = document.createElement('div'); 22 | container.style.position = 'absolute'; 23 | container.style.top = '0px'; 24 | container.style.left = '0px'; 25 | container.style.right = '0px'; 26 | container.style.bottom = '0px'; 27 | container.style.width = scene.canvas.width + "px"; 28 | container.style.height = scene.canvas.height + "px"; 29 | container.style.pointerEvents = "none"; 30 | this._viewer.container.appendChild(container); 31 | this._echartsContainer = container; 32 | (echarts as any).glMap = scene; 33 | this._register(); 34 | return (echarts as any).init(container); 35 | } 36 | _register() { 37 | if (this._isRegistered) return; 38 | (echarts as any).registerCoordinateSystem("GLMap", new RegisterCoordinateSystem((echarts as any).glMap)); 39 | (echarts as any).registerAction({ 40 | type: "GLMapRoam", 41 | event: "GLMapRoam", 42 | update: "updateLayout" 43 | }, function(e: any, t: any) {}); 44 | (echarts as any).extendComponentModel({ 45 | type: "GLMap", 46 | getBMap: function() { 47 | return this.__GLMap; 48 | }, 49 | defaultOption: { 50 | roam: !1 51 | } 52 | }); 53 | (echarts as any).extendComponentView({ 54 | type: "GLMap", 55 | init: function(echartModel: any, api: any) { 56 | this.api = api, (echarts as any).glMap.postRender.addEventListener(this.moveHandler, this); 57 | }, 58 | moveHandler: function(e: any, t: any) { 59 | this.api.dispatchAction({ 60 | type: "GLMapRoam" 61 | }); 62 | }, 63 | render: function(e: any, t, i: any) {}, 64 | dispose: function() { 65 | (echarts as any).glMap.postRender.removeEventListener(this.moveHandler, this); 66 | } 67 | }); 68 | this._isRegistered = true; 69 | } 70 | 71 | dispose() { 72 | this._echartsContainer && (this._viewer.container.removeChild(this._echartsContainer), this._echartsContainer = null); 73 | this._chartLayer && (this._chartLayer.dispose(), this._chartLayer = null); 74 | this._isRegistered = false; 75 | } 76 | 77 | destroy() { 78 | this.dispose(); 79 | } 80 | 81 | updateEchartsLayer(option: any) { 82 | this._chartLayer && this._chartLayer.setOption(option); 83 | } 84 | 85 | getMap() { 86 | return this._viewer; 87 | } 88 | 89 | getEchartsLayer() { 90 | return this._chartLayer; 91 | } 92 | 93 | show() { 94 | this._echartsContainer && (this._echartsContainer.style.visibility = "visible"); 95 | } 96 | 97 | hide() { 98 | this._echartsContainer && (this._echartsContainer.style.visibility = "hidden"); 99 | } 100 | 101 | } 102 | 103 | export default EchartsLayer; 104 | // @ts-check 105 | -------------------------------------------------------------------------------- /src/map/service/leaflet/imageryProvider/index.ts: -------------------------------------------------------------------------------- 1 | import './TileLayerBaidu'; 2 | const baseLayers: Record = { 3 | 高德地图: { 4 | url: 'http://webrd0{s}.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=8&x={x}&y={y}&z={z}', 5 | options: { subdomains: "1234" } 6 | }, 7 | 高德影像: { 8 | url: [ 9 | { 10 | url: 'http://webst0{s}.is.autonavi.com/appmaptile?style=6&x={x}&y={y}&z={z}', 11 | options: { subdomains: "1234" } 12 | }, 13 | { 14 | url: 'http://webst0{s}.is.autonavi.com/appmaptile?x={x}&y={y}&z={z}&lang=zh_cn&size=1&scale=1&style=8', 15 | options: { subdomains: "1234" } 16 | } 17 | ] 18 | }, 19 | 天地图: { 20 | url: [ 21 | { 22 | url: 'http://t{s}.tianditu.gov.cn/vec_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=vec&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILECOL={x}&TILEROW={y}&TILEMATRIX={z}&tk=56b81006f361f6406d0e940d2f89a39c', 23 | options: { subdomains: ['0', '1', '2', '3', '4', '5', '6', '7'] } 24 | }, 25 | { 26 | url: 'http://t{s}.tianditu.gov.cn/cva_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=cva&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILECOL={x}&TILEROW={y}&TILEMATRIX={z}&tk=56b81006f361f6406d0e940d2f89a39c', 27 | options: { subdomains: ['0', '1', '2', '3', '4', '5', '6', '7'] } 28 | } 29 | ] 30 | }, 31 | 天地图影像: { 32 | url: [ 33 | { 34 | url: 'ttp://t{s}.tianditu.gov.cn/img_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=img&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILECOL={x}&TILEROW={y}&TILEMATRIX={z}&tk=56b81006f361f6406d0e940d2f89a39c', 35 | options: { subdomains: ['0', '1', '2', '3', '4', '5', '6', '7'] } 36 | }, 37 | { 38 | url: 'http://t{s}.tianditu.gov.cn/cia_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=cia&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILECOL={x}&TILEROW={y}&TILEMATRIX={z}&tk=56b81006f361f6406d0e940d2f89a39c', 39 | options: { subdomains: ['0', '1', '2', '3', '4', '5', '6', '7'] } 40 | } 41 | ] 42 | }, 43 | 天地图地形: { 44 | url: [ 45 | { 46 | url: 'http://t{s}.tianditu.gov.cn/ter_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=ter&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILECOL={x}&TILEROW={y}&TILEMATRIX={z}&tk=56b81006f361f6406d0e940d2f89a39c', 47 | options: { subdomains: ['0', '1', '2', '3', '4', '5', '6', '7'] } 48 | }, 49 | { 50 | url: 'http://t{s}.tianditu.gov.cn/cta_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=cta&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILECOL={x}&TILEROW={y}&TILEMATRIX={z}&tk=56b81006f361f6406d0e940d2f89a39c', 51 | options: { subdomains: ['0', '1', '2', '3', '4', '5', '6', '7'] } 52 | } 53 | ] 54 | }, 55 | Google地图: { 56 | url: 'http://mt1.google.cn/vt/lyrs=m@207000000&hl=zh-CN&gl=CN&src=app&x={x}&y={y}&z={z}&s=Galile' 57 | }, 58 | 59 | Google影像: { 60 | url: [ 61 | { 62 | url: 'http://mt1.google.cn/vt/lyrs=s&hl=zh-CN&gl=CN&x={x}&y={y}&z={z}&s=Gal', 63 | }, 64 | { 65 | url: 'http://mt1.google.cn/vt/imgtp=png32&lyrs=h@207000000&hl=zh-CN&gl=cn&x={x}&y={y}&z={z}&s=Galil', 66 | } 67 | ] 68 | }, 69 | 70 | "GeoQ": { 71 | url: 'http://map.geoq.cn/ArcGIS/rest/services/ChinaOnlineCommunity/MapServer/tile/{z}/{y}/{x}' 72 | }, 73 | GeoQ藏蓝: { 74 | url: 'http://map.geoq.cn/ArcGIS/rest/services/ChinaOnlineStreetPurplishBlue/MapServer/tile/{z}/{y}/{x}' 75 | }, 76 | GeoQ灰: { 77 | url: 'http://map.geoq.cn/ArcGIS/rest/services/ChinaOnlineStreetGray/MapServer/tile/{z}/{y}/{x}' 78 | } 79 | }; 80 | 81 | export { baseLayers }; 82 | -------------------------------------------------------------------------------- /src/map/service/cesium/imageryProvider/baidu/BaiduMercatorTilingScheme.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @Author: Caven 3 | * @Date: 2021-01-31 19:22:04 4 | */ 5 | import { WebMercatorTilingScheme, Rectangle, defined, Math as CesiumMath, Cartographic, Cartesian2 } from 'cesium'; 6 | import BaiduMercatorProjection from './BaiduMercatorProjection'; 7 | import CoordTransform from '../../../../utils/CoordTransform'; 8 | 9 | class BaiduMercatorTilingScheme extends WebMercatorTilingScheme { 10 | public resolutions: number[] = []; 11 | constructor(options: any = {}) { 12 | super(options); 13 | let projection = new BaiduMercatorProjection(); 14 | (this.projection as any).project = function(cartographic:any, result: any) { 15 | result = result || {}; 16 | result = CoordTransform.WGS84ToGCJ02( 17 | CesiumMath.toDegrees(cartographic.longitude), 18 | CesiumMath.toDegrees(cartographic.latitude) 19 | ); 20 | result = CoordTransform.GCJ02ToBD09(result[0], result[1]); 21 | result[0] = Math.min(result[0], 180); 22 | result[0] = Math.max(result[0], -180); 23 | result[1] = Math.min(result[1], 74.000022); 24 | result[1] = Math.max(result[1], -71.988531); 25 | result = projection.lngLatToPoint({ 26 | lng: result[0], 27 | lat: result[1] 28 | }); 29 | return new Cartesian2(result.x, result.y); 30 | }; 31 | (this.projection as any).unproject = function(cartesian: any, result: any) { 32 | result = result || {}; 33 | result = projection.mercatorToLngLat({ 34 | lng: cartesian.x, 35 | lat: cartesian.y 36 | }); 37 | result = CoordTransform.BD09ToGCJ02(result.lng, result.lat); 38 | result = CoordTransform.GCJ02ToWGS84(result[0], result[1]); 39 | return new Cartographic( 40 | CesiumMath.toRadians(result[0]), 41 | CesiumMath.toRadians(result[1]) 42 | ); 43 | }; 44 | this.resolutions = options.resolutions || []; 45 | } 46 | 47 | /** 48 | * 49 | * @param x 50 | * @param y 51 | * @param level 52 | * @param result 53 | * @returns {module:cesium.Rectangle|*} 54 | */ 55 | tileXYToNativeRectangle(x: number, y: number, level: number, result: any) { 56 | const tileWidth: number = this.resolutions[level]; 57 | const west: number = x * tileWidth; 58 | const east: number = (x + 1) * tileWidth; 59 | const north: number = ((y = -y) + 1) * tileWidth; 60 | const south: number = y * tileWidth; 61 | 62 | if (!defined(result)) { 63 | return new Rectangle(west, south, east, north); 64 | } 65 | 66 | result.west = west; 67 | result.south = south; 68 | result.east = east; 69 | result.north = north; 70 | return result; 71 | } 72 | 73 | /** 74 | * 75 | * @param position 76 | * @param level 77 | * @param result 78 | * @returns {undefined|*} 79 | */ 80 | positionToTileXY(position: any, level: number, result: any) { 81 | const rectangle: any = this.rectangle; 82 | if (!Rectangle.contains(rectangle, position)) { 83 | return undefined; 84 | } 85 | const projection: any = this.projection; 86 | const webMercatorPosition: Record = projection.project(position); 87 | if (!defined(webMercatorPosition)) { 88 | return undefined; 89 | } 90 | const tileWidth: number = this.resolutions[level]; 91 | const xTileCoordinate: number = Math.floor(webMercatorPosition.x / tileWidth); 92 | const yTileCoordinate: number = -Math.floor(webMercatorPosition.y / tileWidth); 93 | if (!defined(result)) { 94 | return new Cartesian2(xTileCoordinate, yTileCoordinate); 95 | } 96 | result.x = xTileCoordinate; 97 | result.y = yTileCoordinate; 98 | return result; 99 | } 100 | } 101 | 102 | export default BaiduMercatorTilingScheme; 103 | -------------------------------------------------------------------------------- /src/views/modelManage/CesiumBaseModel.vue: -------------------------------------------------------------------------------- 1 | 5 | 6 | 92 | 93 | 100 | -------------------------------------------------------------------------------- /src/mock/line/stationList1.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "code": "LYSLJ_RIVER_70102550", 4 | "level": null, 5 | "latitude": "30.265277", 6 | "watershedId": "60601", 7 | "pollutants": [ 8 | { 9 | "overProof": null, 10 | "bstel": 0.0, 11 | "code": "w99030", 12 | "mpFlag": false, 13 | "grade": null, 14 | "name": "", 15 | "value": 0.0 16 | }, 17 | { 18 | "overProof": null, 19 | "bstel": 0.0, 20 | "code": "e01201", 21 | "mpFlag": false, 22 | "grade": null, 23 | "name": "", 24 | "value": 2.26 25 | } 26 | ], 27 | "regionId": "659024", 28 | "controlLevel": "003", 29 | "monitoringMethods": 1, 30 | "accessCode": "LYSLJ_RIVER_70102550", 31 | "name": "三堡船闸外", 32 | "property": null, 33 | "online": 1, 34 | "id": "14224", 35 | "time": "2021-06-30 03:10:00", 36 | "runState": 1, 37 | "mainPollutant": null, 38 | "longitude": "120.221388" 39 | }, 40 | { 41 | "code": "SW7104", 42 | "regionId": "659051", 43 | "controlLevel": "003", 44 | "monitoringMethods": 1, 45 | "latitude": "30.29785", 46 | "accessCode": "SW7104", 47 | "name": "沿山河沈家桥(拱墅区)", 48 | "property": null, 49 | "id": "14225", 50 | "watershedId": "60601", 51 | "longitude": "120.08772" 52 | }, 53 | { 54 | "code": "LYSLJ_RESERVOIR_70116224", 55 | "level": null, 56 | "latitude": "29.955361", 57 | "watershedId": "70708168", 58 | "pollutants": [ 59 | { 60 | "overProof": null, 61 | "bstel": 0.0, 62 | "code": "e01201", 63 | "mpFlag": false, 64 | "grade": null, 65 | "name": "", 66 | "value": 135.82 67 | } 68 | ], 69 | "regionId": "659094", 70 | "controlLevel": "003", 71 | "monitoringMethods": 1, 72 | "accessCode": "LYSLJ_RESERVOIR_70116224", 73 | "name": "渌渚西坞水库", 74 | "property": null, 75 | "online": 1, 76 | "id": "14227", 77 | "time": "2021-06-30 03:10:00", 78 | "runState": 1, 79 | "mainPollutant": null, 80 | "longitude": "119.789778" 81 | }, 82 | { 83 | "code": "SW69703", 84 | "level": null, 85 | "latitude": "30.3875", 86 | "watershedId": "60601", 87 | "pollutants": [ 88 | { 89 | "overProof": null, 90 | "bstel": 0.0, 91 | "code": "e01201", 92 | "mpFlag": false, 93 | "grade": null, 94 | "name": "", 95 | "value": 3.72 96 | } 97 | ], 98 | "regionId": "659197", 99 | "controlLevel": "003", 100 | "monitoringMethods": 1, 101 | "accessCode": "SW69703", 102 | "name": "潘板(林水)", 103 | "property": null, 104 | "online": 0, 105 | "id": "14230", 106 | "time": "2021-05-07 19:00:00", 107 | "runState": 0, 108 | "mainPollutant": null, 109 | "longitude": "119.8725" 110 | }, 111 | { 112 | "code": "SW7102", 113 | "level": null, 114 | "latitude": "30.29785", 115 | "watershedId": "60601", 116 | "pollutants": [ 117 | { 118 | "overProof": null, 119 | "bstel": 0.0, 120 | "code": "e01201", 121 | "mpFlag": false, 122 | "grade": null, 123 | "name": "", 124 | "value": 1.94 125 | } 126 | ], 127 | "regionId": "659051", 128 | "controlLevel": "003", 129 | "monitoringMethods": 1, 130 | "accessCode": "SW7102", 131 | "name": "上塘河半山桥(拱墅区)", 132 | "property": null, 133 | "online": 0, 134 | "id": "14232", 135 | "time": "2021-05-07 19:00:00", 136 | "runState": 0, 137 | "mainPollutant": null, 138 | "longitude": "120.08772" 139 | } 140 | ] 141 | -------------------------------------------------------------------------------- /src/map/service/LeafletService.ts: -------------------------------------------------------------------------------- 1 | import './leaflet/load'; 2 | const L = window.L; 3 | import { BaseIconOptions, CircleMarker, CircleMarkerOptions, CRS, DivIcon, DivIconOptions, Icon, IconOptions, latLng, latLngBounds, LatLngExpression, Layer, LayerGroup, LayerOptions, Map, Marker, MarkerOptions, TileLayer } from 'leaflet'; 4 | import MapService from '../common/MapService'; 5 | import { LeafletInstanceOptions } from '../type/LeafletType'; 6 | import { BaseMap, ChangeLayerImageConfig, LayerImagesEnum, MapTypeEnum } from '@/map/type/CommonType'; 7 | import CommonStore from '../common/CommonStore'; 8 | import { baseLayers } from '../service/leaflet/imageryProvider'; 9 | import LeafletMarkerCluster from './leaflet/markerCluster/LeafletMarkerCluster'; 10 | 11 | export default class LeafletService extends MapService implements BaseMap { 12 | public leafletMarkerCluster: LeafletMarkerCluster; 13 | constructor(props: LeafletInstanceOptions) { 14 | super(); 15 | this.leafletMarkerCluster = new LeafletMarkerCluster(L); 16 | } 17 | 18 | private layerUrl: string = 'http://{s}.tile.osm.org/{z}/{x}/{y}.png'; 19 | 20 | /** 21 | * 初始化地图实例 22 | * @param type 23 | * @param props 24 | * @protected 25 | */ 26 | public async initMapInstance(type: MapTypeEnum, props: LeafletInstanceOptions) { 27 | const mapInstanceCache: any = await CommonStore.getInstance('LEAFLET'); 28 | if (mapInstanceCache) { 29 | return mapInstanceCache; 30 | } 31 | const map: Map = new Map(props.id, { 32 | crs: CRS.EPSG3857, 33 | center: [30, 120], 34 | maxZoom: 18, 35 | minZoom: 5, 36 | maxBounds: latLngBounds(latLng(4, 73), latLng(54, 135)), 37 | zoom: 14, 38 | zoomControl: false 39 | }); 40 | const titleLayer: TileLayer.WMS = new TileLayer.WMS(this.layerUrl,{ 41 | format: 'image/png', 42 | layers: '全国县@全国县', 43 | transparent: true, 44 | }); 45 | map.addLayer(titleLayer); 46 | CommonStore.setInstance(type, map); 47 | return map; 48 | } 49 | 50 | /** 51 | * 修改底图 52 | * @param type 53 | * @param config 54 | * @param instance 55 | */ 56 | public changeLayer(type: LayerImagesEnum, config: ChangeLayerImageConfig, instance: T): T { 57 | let layer: any = null; 58 | if (baseLayers.hasOwnProperty(type)){ 59 | if (Array.isArray(baseLayers[type].url)) { 60 | const urls: any = []; 61 | for (let i = 0; i < baseLayers[type].url.length; i ++) { 62 | urls.push(new TileLayer(baseLayers[type].url[i].url, baseLayers[type].url[i].options)); 63 | } 64 | layer = new LayerGroup(urls); 65 | } else { 66 | layer = new TileLayer(baseLayers[type].url, baseLayers[type].url.options); 67 | } 68 | 69 | } 70 | instance.addLayer(layer); 71 | return instance; 72 | } 73 | 74 | /** 75 | * 创建divIcon 76 | * @param options 77 | */ 78 | public createDivIon(options?: DivIconOptions): DivIcon { 79 | return new DivIcon(options); 80 | } 81 | 82 | /** 83 | * 创建普通的icon 84 | * @param options 85 | */ 86 | public createIcon(options: T): Icon { 87 | return new Icon(options); 88 | } 89 | 90 | /** 91 | * 渲染marker 92 | * @param latlng 93 | * @param options 94 | */ 95 | public createMarker(latlng: LatLngExpression, options?: MarkerOptions): Marker { 96 | return new Marker(latlng, options); 97 | } 98 | 99 | /** 100 | * 绘制原点 marker 101 | * @param latlng 102 | * @param options 103 | */ 104 | public renderCircleMarker(latlng: LatLngExpression, options?: CircleMarkerOptions): CircleMarker { 105 | return new CircleMarker(latlng, options); 106 | } 107 | 108 | /** 109 | * 多个图层合并成图层组 110 | * @param instance 111 | * @param layers 112 | * @param options 113 | */ 114 | public renderMarkerToGroupLayer(instance: Map, layers?: Layer[], options?: LayerOptions): LayerGroup { 115 | const layerGroup: LayerGroup = new LayerGroup(layers, options); 116 | instance.addLayer(layerGroup); 117 | return layerGroup; 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "simple-gis-web", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "src/main.ts", 6 | "scripts": { 7 | "lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix", 8 | "webpack:dev": "webpack serve --config ./build/webpack_dev.config --env development --mode development --hot", 9 | "webpack:build": "webpack --config ./build/webpack_build.config --mode production", 10 | "webpack:analyzer:": "webpack --config ./build/webpack_analyzer.config --mode production", 11 | "test": "echo \"Error: no test specified\" && exit 1" 12 | }, 13 | "dependencies": { 14 | "@babel/polyfill": "^7.12.1", 15 | "@babel/runtime": "^7.12.5", 16 | "@supermap/iclient-leaflet": "^10.1.3", 17 | "@types/cesium": "^1.67.13", 18 | "axios": "^0.19.2", 19 | "cesium": "^1.82.1", 20 | "echarts": "^4.6.0", 21 | "element-ui": "^2.15.2", 22 | "leaflet": "^1.7.1", 23 | "leaflet.markercluster": "^1.5.0", 24 | "mapbox-gl": "^2.3.0", 25 | "process": "^0.11.10", 26 | "proj4": "^2.7.2", 27 | "proj4leaflet": "^1.0.2", 28 | "qs": "^6.10.1", 29 | "util": "^0.12.4", 30 | "vue": "^2.6.11", 31 | "vue-router": "^3.1.6", 32 | "vuex": "^3.1.3" 33 | }, 34 | "devDependencies": { 35 | "@babel/cli": "^7.13.14", 36 | "@babel/core": "^7.13.15", 37 | "@babel/plugin-proposal-class-properties": "^7.13.0", 38 | "@babel/plugin-proposal-decorators": "^7.13.15", 39 | "@babel/plugin-syntax-dynamic-import": "^7.8.3", 40 | "@babel/plugin-transform-runtime": "^7.14.2", 41 | "@babel/preset-env": "^7.13.15", 42 | "@babel/preset-typescript": "^7.13.0", 43 | "@types/echarts": "^4.9.10", 44 | "@types/leaflet": "^1.7.1", 45 | "@types/mapbox-gl": "^2.1.2", 46 | "@types/node": "^15.14.0", 47 | "@types/qs": "^6.9.6", 48 | "@typescript-eslint/eslint-plugin": "^3.0.2", 49 | "@typescript-eslint/parser": "^3.10.1", 50 | "autoprefixer": "^10.2.5", 51 | "babel-eslint": "^10.1.0", 52 | "babel-loader": "^8.2.2", 53 | "babel-plugin-component": "^1.1.1", 54 | "babel-plugin-import": "^1.13.3", 55 | "clean-webpack-plugin": "^3.0.0", 56 | "copy-webpack-plugin": "^6.0.2", 57 | "css-loader": "^5.2.2", 58 | "css-minimizer-webpack-plugin": "^3.0.0", 59 | "eslint": "^7.1.0", 60 | "eslint-config-prettier": "^6.15.0", 61 | "eslint-plugin-html": "^6.1.2", 62 | "eslint-plugin-import": "^2.22.1", 63 | "eslint-plugin-vue": "^7.9.0", 64 | "html-loader": "^2.1.2", 65 | "html-webpack-plugin": "^5.3.1", 66 | "json-loader": "^0.5.7", 67 | "less": "^3.11.3", 68 | "less-loader": "^6.1.2", 69 | "mini-css-extract-plugin": "^1.6.0", 70 | "postcss-loader": "^4.2.0", 71 | "pug": "^3.0.2", 72 | "pug-html-loader": "^1.1.5", 73 | "pug-plain-loader": "^1.1.0", 74 | "sass-loader": "^11.0.1", 75 | "speed-measure-webpack-plugin": "^1.5.0", 76 | "style-loader": "^2.0.0", 77 | "stylus": "^0.54.8", 78 | "stylus-loader": "^5.0.0", 79 | "terser-webpack-plugin": "^4.2.2", 80 | "ts-loader": "^8.1.0", 81 | "tsconfig-paths": "^3.9.0", 82 | "tslib": "^2.2.0", 83 | "typescript": "^4.2.4", 84 | "vue-class-component": "^7.2.6", 85 | "vue-loader": "^15.9.6", 86 | "vue-property-decorator": "^9.1.2", 87 | "vue-style-loader": "^4.1.3", 88 | "vue-template-compiler": "^2.6.11", 89 | "vuex-class": "^0.3.2", 90 | "vuex-module-decorators": "^1.0.1", 91 | "webpack": "^5.36.2", 92 | "webpack-bundle-analyzer": "^4.4.1", 93 | "webpack-cli": "^4.7.0", 94 | "webpack-dev-server": "^3.11.2", 95 | "yaml-loader": "^0.6.0" 96 | }, 97 | "repository": { 98 | "type": "git", 99 | "url": "git+https://github.com/canyuegongzi/t-cli-template.git" 100 | }, 101 | "author": "", 102 | "license": "ISC", 103 | "bugs": { 104 | "url": "https://github.com/canyuegongzi/t-cli-template/issues" 105 | }, 106 | "homepage": "https://github.com/canyuegongzi/t-cli-template#readme", 107 | "browserslist": [ 108 | "defaults", 109 | "not ie <= 10", 110 | "last 2 versions", 111 | "> 1%", 112 | "iOS >= 7", 113 | "Android >= 8.0" 114 | ] 115 | } 116 | -------------------------------------------------------------------------------- /src/mock/polygon/mockPolygon.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "FeatureCollection", 3 | "features": [ 4 | { 5 | "type": "Feature", 6 | "properties": {}, 7 | "geometry": { 8 | "type": "Polygon", 9 | "coordinates": [ 10 | [ 11 | [ 12 | 120.1471710205078, 13 | 30.29168195585223 14 | ], 15 | [ 16 | 120.26046752929688, 17 | 30.355101405951 18 | ], 19 | [ 20 | 120.22201538085938, 21 | 30.370505537135568 22 | ], 23 | [ 24 | 120.17463684082031, 25 | 30.372875188118016 26 | ], 27 | [ 28 | 120.15953063964844, 29 | 30.36813582872057 30 | ], 31 | [ 32 | 120.08193969726562, 33 | 30.315987718557867 34 | ], 35 | [ 36 | 120.09498596191406, 37 | 30.329620019722665 38 | ], 39 | [ 40 | 120.11970520019533, 41 | 30.3391022406564 42 | ], 43 | [ 44 | 120.14236450195312, 45 | 30.337917013258718 46 | ], 47 | [ 48 | 120.17669677734374, 49 | 30.326063950143894 50 | ], 51 | [ 52 | 120.18081665039061, 53 | 30.313616689930676 54 | ], 55 | [ 56 | 120.1636505126953, 57 | 30.267963210548913 58 | ], 59 | [ 60 | 120.13000488281249, 61 | 30.28041626667403 62 | ], 63 | [ 64 | 120.10940551757812, 65 | 30.273300428069934 66 | ], 67 | [ 68 | 120.08949279785156, 69 | 30.253729211980726 70 | ], 71 | [ 72 | 120.10528564453125, 73 | 30.209828066454087 74 | ], 75 | [ 76 | 120.11558532714842, 77 | 30.175405362307902 78 | ], 79 | [ 80 | 120.17051696777344, 81 | 30.164720007924867 82 | ], 83 | [ 84 | 120.22750854492186, 85 | 30.18787014479982 86 | ], 87 | [ 88 | 120.2405548095703, 89 | 30.21576179908697 90 | ], 91 | [ 92 | 120.21034240722655, 93 | 30.211608223816906 94 | ], 95 | [ 96 | 120.18356323242188, 97 | 30.21457508118796 98 | ], 99 | [ 100 | 120.16090393066405, 101 | 30.22466172703242 102 | ], 103 | [ 104 | 120.20210266113281, 105 | 30.237713497892038 106 | ], 107 | [ 108 | 120.21652221679688, 109 | 30.267370168467806 110 | ], 111 | [ 112 | 120.23368835449219, 113 | 30.2910890570962 114 | ], 115 | [ 116 | 120.1471710205078, 117 | 30.29168195585223 118 | ] 119 | ] 120 | ] 121 | } 122 | } 123 | ] 124 | } 125 | -------------------------------------------------------------------------------- /src/views/Main.vue: -------------------------------------------------------------------------------- 1 | 23 | 24 | 120 | 121 | 148 | 152 | -------------------------------------------------------------------------------- /src/directives/draggable.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue'; 2 | 3 | // 自定义元素实现弹框拖拽[重点] 4 | Vue.directive('draw', { 5 | 6 | inserted: function(el, binding, vNode) { 7 | el.setAttribute('style', 'position: fixed; z-index: 9999'); 8 | }, 9 | 10 | bind: function(el, bindding, vNode) { 11 | el.setAttribute('draggable', true); 12 | let left, top, width, height; 13 | el._dragstart = function(event) { 14 | event.stopPropagation(); 15 | left = event.clientX - el.offsetLeft; 16 | top = event.clientY - el.offsetTop; 17 | width = el.offsetWidth; 18 | height = el.offsetHeight; 19 | }; 20 | el._checkPosition = function() { // 防止被拖出边界 21 | let width = el.offsetWidth; 22 | let height = el.offsetHeight; 23 | let left = Math.min(el.offsetLeft, document.body.clientWidth - width); 24 | left = Math.max(0, left); 25 | let top = Math.min(el.offsetTop, document.body.clientHeight - height); 26 | top = Math.max(0, top); 27 | el.style.left = left + 'px'; 28 | el.style.top = top + 'px'; 29 | //el.style.width = width + 'px'; 30 | //el.style.height = height + 'px'; 31 | }; 32 | el._dragEnd = function(event) { 33 | event.stopPropagation(); 34 | left = event.clientX - left; 35 | top = event.clientY - top; 36 | el.style.left = left + 'px'; 37 | el.style.top = top + 'px'; 38 | //el.style.width = width + 'px'; 39 | //el.style.height = height + 'px'; 40 | el._checkPosition(); 41 | }; 42 | el._documentAllowDraop = function(event) { 43 | event.preventDefault(); 44 | }; 45 | document.body.addEventListener('dragover', el._documentAllowDraop); 46 | el.addEventListener('dragstart', el._dragstart); 47 | el.addEventListener('dragend', el._dragEnd); 48 | window.addEventListener('resize', el._checkPosition); 49 | }, 50 | 51 | unbind: function(el, bindding, vNode) { 52 | document.body.removeEventListener('dragover', el._documentAllowDraop); 53 | el.removeEventListener('dragstart', el._dragstart); 54 | el.removeEventListener('dragend', el._dragEnd); 55 | window.removeEventListener('resize', el._checkPosition); 56 | delete el._documentAllowDraop; 57 | delete el._dragstart; 58 | delete el._dragEnd; 59 | delete el._checkPosition; 60 | }, 61 | }); 62 | 63 | // v-dialogDrag: 弹窗拖拽 64 | Vue.directive('dialogDrag', { 65 | bind(el, binding, vnode, oldVnode) { 66 | const dialogHeaderEl = el.querySelector('.el-dialog__header'); 67 | const dragDom = el.querySelector('.el-dialog'); 68 | dialogHeaderEl.style.cursor = 'move'; 69 | 70 | // 获取原有属性 ie dom元素.currentStyle 火狐谷歌 window.getComputedStyle(dom元素, null); 71 | const sty = dragDom.currentStyle || window.getComputedStyle(dragDom, null); 72 | 73 | dialogHeaderEl.onmousedown = (e) => { 74 | // 鼠标按下,计算当前元素距离可视区的距离 75 | const disX = e.clientX - dialogHeaderEl.offsetLeft; 76 | const disY = e.clientY - dialogHeaderEl.offsetTop; 77 | 78 | // 获取到的值带px 正则匹配替换 79 | let styL, styT; 80 | 81 | // 注意在ie中 第一次获取到的值为组件自带50% 移动之后赋值为px 82 | if (sty.left.includes('%')) { 83 | styL = +document.body.clientWidth * (+sty.left.replace(/\%/g, '') / 100); 84 | styT = +document.body.clientHeight * (+sty.top.replace(/\%/g, '') / 100); 85 | } else { 86 | styL = +sty.left.replace(/\px/g, ''); 87 | styT = +sty.top.replace(/\px/g, ''); 88 | } 89 | 90 | document.onmousemove = function(e) { 91 | // 通过事件委托,计算移动的距离 92 | const l = e.clientX - disX; 93 | const t = e.clientY - disY; 94 | 95 | // 移动当前元素 96 | dragDom.style.left = `${l + styL}px`; 97 | dragDom.style.top = `${t + styT}px`; 98 | 99 | // 将此时的位置传出去 100 | // binding.value({x:e.pageX,y:e.pageY}) 101 | }; 102 | 103 | document.onmouseup = function(e) { 104 | document.onmousemove = null; 105 | document.onmouseup = null; 106 | }; 107 | }; 108 | }, 109 | }); 110 | 111 | // v-dialogDragWidth: 弹窗宽度拖大 拖小 112 | Vue.directive('dialogDragWidth', { 113 | bind(el, binding, vnode, oldVnode) { 114 | const dragDom = binding.value.$el.querySelector('.el-dialog'); 115 | 116 | el.onmousedown = (e) => { 117 | // 鼠标按下,计算当前元素距离可视区的距离 118 | const disX = e.clientX - el.offsetLeft; 119 | 120 | document.onmousemove = function(e) { 121 | e.preventDefault(); // 移动时禁用默认事件 122 | 123 | // 通过事件委托,计算移动的距离 124 | const l = e.clientX - disX; 125 | dragDom.style.width = `${l}px`; 126 | }; 127 | 128 | document.onmouseup = function(e) { 129 | document.onmousemove = null; 130 | document.onmouseup = null; 131 | }; 132 | }; 133 | }, 134 | }); 135 | -------------------------------------------------------------------------------- /src/map/utils/CoordTransform.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * 坐标转换 3 | */ 4 | const BD_FACTOR = (3.14159265358979324 * 3000.0) / 180.0; 5 | const PI = 3.1415926535897932384626; 6 | const RADIUS = 6378245.0; 7 | const EE = 0.00669342162296594323; 8 | 9 | class CoordTransform { 10 | /** 11 | * BD-09 To GCJ-02 12 | * @param lng 13 | * @param lat 14 | * @returns {number[]} 15 | */ 16 | static BD09ToGCJ02(lng: number, lat: number): number[] { 17 | let x: number = +lng - 0.0065; 18 | let y: number = +lat - 0.006; 19 | let z: number = Math.sqrt(x * x + y * y) - 0.00002 * Math.sin(y * BD_FACTOR); 20 | let theta: number = Math.atan2(y, x) - 0.000003 * Math.cos(x * BD_FACTOR); 21 | let gg_lng: number = z * Math.cos(theta); 22 | let gg_lat: number = z * Math.sin(theta); 23 | return [gg_lng, gg_lat]; 24 | } 25 | 26 | /** 27 | * GCJ-02 To BD-09 28 | * @param lng 29 | * @param lat 30 | * @returns {number[]} 31 | * @constructor 32 | */ 33 | static GCJ02ToBD09(lng: number, lat: number): number[] { 34 | lat = +lat; 35 | lng = +lng; 36 | let z = 37 | Math.sqrt(lng * lng + lat * lat) + 0.00002 * Math.sin(lat * BD_FACTOR); 38 | let theta: number = Math.atan2(lat, lng) + 0.000003 * Math.cos(lng * BD_FACTOR); 39 | let bd_lng: number = z * Math.cos(theta) + 0.0065; 40 | let bd_lat: number = z * Math.sin(theta) + 0.006; 41 | return [bd_lng, bd_lat]; 42 | } 43 | 44 | /** 45 | * WGS-84 To GCJ-02 46 | * @param lng 47 | * @param lat 48 | * @returns {number[]} 49 | */ 50 | static WGS84ToGCJ02(lng: number, lat: number): number[] { 51 | lat = +lat; 52 | lng = +lng; 53 | if (this.out_of_china(lng, lat)) { 54 | return [lng, lat]; 55 | } else { 56 | let d = this.delta(lng, lat); 57 | return [lng + d[0], lat + d[1]]; 58 | } 59 | } 60 | 61 | /** 62 | * GCJ-02 To WGS-84 63 | * @param lng 64 | * @param lat 65 | * @returns {number[]} 66 | * @constructor 67 | */ 68 | static GCJ02ToWGS84(lng: number, lat: number): number[] { 69 | lat = +lat; 70 | lng = +lng; 71 | if (this.out_of_china(lng, lat)) { 72 | return [lng, lat]; 73 | } else { 74 | let d: number[] = this.delta(lng, lat); 75 | let mgLng = lng + d[0]; 76 | let mgLat = lat + d[1]; 77 | return [lng * 2 - mgLng, lat * 2 - mgLat]; 78 | } 79 | } 80 | 81 | /** 82 | * 83 | * @param lng 84 | * @param lat 85 | * @returns {number[]} 86 | */ 87 | static delta(lng: number, lat: number): number[] { 88 | let dLng: number = this.transformLng(lng - 105, lat - 35); 89 | let dLat: number = this.transformLat(lng - 105, lat - 35); 90 | const radLat: number = (lat / 180) * PI; 91 | let magic: number = Math.sin(radLat); 92 | magic = 1 - EE * magic * magic; 93 | const sqrtMagic: number = Math.sqrt(magic); 94 | dLng = (dLng * 180) / ((RADIUS / sqrtMagic) * Math.cos(radLat) * PI); 95 | dLat = (dLat * 180) / (((RADIUS * (1 - EE)) / (magic * sqrtMagic)) * PI); 96 | return [dLng, dLat]; 97 | } 98 | 99 | /** 100 | * 101 | * @param lng 102 | * @param lat 103 | * @returns {number} 104 | */ 105 | static transformLng(lng: number, lat: number): number { 106 | lat = +lat; 107 | lng = +lng; 108 | let ret = 109 | 300.0 + 110 | lng + 111 | 2.0 * lat + 112 | 0.1 * lng * lng + 113 | 0.1 * lng * lat + 114 | 0.1 * Math.sqrt(Math.abs(lng)); 115 | ret += 116 | ((20.0 * Math.sin(6.0 * lng * PI) + 20.0 * Math.sin(2.0 * lng * PI)) * 117 | 2.0) / 118 | 3.0; 119 | ret += 120 | ((20.0 * Math.sin(lng * PI) + 40.0 * Math.sin((lng / 3.0) * PI)) * 2.0) / 121 | 3.0; 122 | ret += 123 | ((150.0 * Math.sin((lng / 12.0) * PI) + 124 | 300.0 * Math.sin((lng / 30.0) * PI)) * 125 | 2.0) / 126 | 3.0; 127 | return ret; 128 | } 129 | 130 | /** 131 | * 132 | * @param lng 133 | * @param lat 134 | * @returns {number} 135 | */ 136 | static transformLat(lng: number, lat: number): number { 137 | lat = +lat; 138 | lng = +lng; 139 | let ret = 140 | -100.0 + 141 | 2.0 * lng + 142 | 3.0 * lat + 143 | 0.2 * lat * lat + 144 | 0.1 * lng * lat + 145 | 0.2 * Math.sqrt(Math.abs(lng)); 146 | ret += 147 | ((20.0 * Math.sin(6.0 * lng * PI) + 20.0 * Math.sin(2.0 * lng * PI)) * 148 | 2.0) / 149 | 3.0; 150 | ret += 151 | ((20.0 * Math.sin(lat * PI) + 40.0 * Math.sin((lat / 3.0) * PI)) * 2.0) / 152 | 3.0; 153 | ret += 154 | ((160.0 * Math.sin((lat / 12.0) * PI) + 155 | 320 * Math.sin((lat * PI) / 30.0)) * 156 | 2.0) / 157 | 3.0; 158 | return ret; 159 | } 160 | 161 | /** 162 | * 163 | * @param lng 164 | * @param lat 165 | * @returns {boolean} 166 | */ 167 | static out_of_china(lng: number, lat: number): boolean { 168 | lat = +lat; 169 | lng = +lng; 170 | return !(lng > 73.66 && lng < 135.05 && lat > 3.86 && lat < 53.55); 171 | } 172 | } 173 | 174 | export default CoordTransform; 175 | -------------------------------------------------------------------------------- /src/map/service/cesium/widgets/CesiumClusterWidgets.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @author fei_yong 3 | * @since 2021-07-010 9:39 4 | * @desc cesium 聚合点位类 5 | */ 6 | 7 | import { GeoJsonDataSource, Resource, Viewer, Event, VerticalOrigin, Entity, Color, HorizontalOrigin, EntityCluster, DataSource } from 'cesium'; 8 | 9 | interface ClusterWidgetsOption { 10 | viewer: Viewer; // 地图实例 11 | data: Resource; // geoJson 格式的点位数据 12 | clustering?: EntityCluster; // 点位聚合形态 13 | rebuildCluster?: (clusteredEntities: any[], cluster: any) => void // 动态重建聚合点样式 14 | selectedEntity?: (e: any) => void // 点击事件回调 15 | } 16 | 17 | export class CesiumClusterWidgets { 18 | 19 | private viewer: Viewer; 20 | 21 | private readonly data: Resource; 22 | 23 | private removeListener: Event.RemoveCallback; 24 | 25 | private cluserLayerResource: DataSource | null; 26 | 27 | private geoJsonDataSource: any; // cesium 加载后的geo 28 | 29 | constructor(options: ClusterWidgetsOption) { 30 | this.viewer = options.viewer; 31 | this.data = options.data; 32 | if (options.rebuildCluster && typeof options.rebuildCluster === 'function') { 33 | this.rebuildCluster = options.rebuildCluster; 34 | } 35 | if (options.selectedEntity && typeof options.selectedEntity === 'function') { 36 | console.log(22222); 37 | this.selectedEntityChanged = options.selectedEntity; 38 | } 39 | this.initCluser(options).then(r => { 40 | }); 41 | this.viewer.selectedEntityChanged.addEventListener(this.selectedEntityChanged); 42 | } 43 | 44 | /** 45 | * 初始化聚合 46 | * @private 47 | */ 48 | private async initCluser(options: ClusterWidgetsOption) { 49 | const geoJsonDataSource: GeoJsonDataSource = await GeoJsonDataSource.load(this.data); 50 | this.cluserLayerResource = await this.viewer.dataSources.add(geoJsonDataSource); 51 | 52 | // 设置聚合的形态 53 | geoJsonDataSource.clustering.enabled = typeof options.clustering?.enabled === 'boolean' ? options.clustering?.enabled : true; 54 | geoJsonDataSource.clustering.clusterLabels = typeof options.clustering?.clusterLabels === 'boolean' ? options.clustering?.clusterLabels : false; 55 | geoJsonDataSource.clustering.pixelRange = options.clustering?.pixelRange || 15; 56 | geoJsonDataSource.clustering.minimumClusterSize = options.clustering?.minimumClusterSize || 3; 57 | 58 | this.setClusterEvent(geoJsonDataSource); 59 | 60 | geoJsonDataSource.entities.values.forEach((entity: Entity) => { 61 | // @ts-ignore 62 | entity.billboard.image = require('../../../../assets/map/site.png'); 63 | // entity.cameraCode = entity._properties.CAMERACODE._value;//设置entity的属性 64 | // @ts-ignore 65 | entity.type = 'cluser'; 66 | //如果有高度信息 需要重新赋值 67 | // let cartographic = Cesium.Cartographic.fromCartesian(entity.position._value);基本要素 68 | // let longitude = Cesium.Math.toDegrees(cartographic.longitude); 69 | // let latitude = Cesium.Math.toDegrees(cartographic.latitude); 70 | // entity.position = Cesium.Cartesian3.fromDegrees(longitude, latitude, Number(entity._properties.Z._value)); 71 | }); 72 | this.geoJsonDataSource = geoJsonDataSource; 73 | } 74 | 75 | /** 76 | * 点击事件监听 77 | * @param geoJsonDataSource 78 | * @private 79 | */ 80 | private setClusterEvent(geoJsonDataSource: GeoJsonDataSource) { 81 | this.removeListener = geoJsonDataSource.clustering.clusterEvent.addEventListener( 82 | (clusteredEntities: any[], cluster: any) => { 83 | this.rebuildCluster(clusteredEntities, cluster); 84 | }, 85 | ); 86 | } 87 | 88 | /** 89 | * 实体点击 90 | * @param e 91 | * @private 92 | */ 93 | private selectedEntityChanged(e: any) { 94 | console.log(e); 95 | // console.log(e)能够拿到选中的实体 如果是聚合对象 e.id为一个entity数组 个数为聚合个数 96 | } 97 | 98 | /** 99 | * 聚合销毁 100 | * @private 101 | */ 102 | public destroy() { 103 | // 销毁掉事件监听 104 | this.removeListener(); 105 | this.viewer.dataSources.remove(this.cluserLayerResource as DataSource); 106 | this.cluserLayerResource = null; 107 | } 108 | 109 | /** 110 | * 聚合点样式重写 111 | * @param clusteredEntities 112 | * @param cluster 113 | * @private 114 | */ 115 | private rebuildCluster(clusteredEntities: any[], cluster: any) { 116 | cluster.billboard.show = true; 117 | cluster.label.show = true; 118 | cluster.label.text = clusteredEntities.length + ''; 119 | cluster.label.scale = 0.5; 120 | cluster.label.fillColor = Color.RED; 121 | cluster.label.color = Color.RED; 122 | // cluster.label.pointOutlineColor = Color.T; 123 | cluster.label.pointOutlineWidth = 0; 124 | cluster.label.verticalOrigin = VerticalOrigin.CENTER; 125 | cluster.label.horizontalOrigin = HorizontalOrigin.CENTER; 126 | cluster.label.showBackground = true; 127 | cluster.label.backgroundColor = Color.TRANSPARENT; 128 | // cluster.label.labelOutlineColor = Color.TRANSPARENT; 129 | cluster.label.labelOutlineWidth = 0; 130 | 131 | cluster.billboard.id = cluster.label.id; 132 | cluster.billboard.verticalOrigin = VerticalOrigin.CENTER; 133 | cluster.billboard.image = require('../../../../assets/map/site-5.png'); 134 | cluster.billboard.width = 28; 135 | cluster.billboard.height = 28; 136 | } 137 | } 138 | 139 | -------------------------------------------------------------------------------- /src/map/service/cesium/imageryProvider/baidu/BaiduImageryProvider.ts: -------------------------------------------------------------------------------- 1 | import { ImageryProvider, Cartesian2, WebMercatorTilingScheme, DeveloperError } from 'cesium'; 2 | import BaiduMercatorTilingScheme from './BaiduMercatorTilingScheme'; 3 | 4 | const IMG_URL: string = 'http://shangetu{s}.map.bdimg.com/it/u=x={x};y={y};z={z};v=009;type=sate&fm=46'; 5 | 6 | const VEC_URL: string = 'http://online{s}.map.bdimg.com/tile/?qt=tile&x={x}&y={y}&z={z}&styles=sl&v=020'; 7 | 8 | const CUSTOM_URL: string = 'http://api{s}.map.bdimg.com/customimage/tile?&x={x}&y={y}&z={z}&scale=1&customid={style}'; 9 | 10 | class BaiduImageryProvider { 11 | 12 | public _tileWidth: number; 13 | 14 | public _tileHeight: number; 15 | 16 | public _maximumLevel: number; 17 | 18 | public _rectangle: any; 19 | 20 | public _credit: any; 21 | 22 | public _crs: any; 23 | 24 | public _style: any; 25 | 26 | public _tilingScheme: any; 27 | 28 | public _url: any; 29 | 30 | public _token: any; 31 | 32 | constructor(options: any = {}) { 33 | this._url = 34 | options.style === 'img' 35 | ? IMG_URL 36 | : options.style === 'vec' 37 | ? VEC_URL 38 | : CUSTOM_URL; 39 | this._tileWidth = 256; 40 | this._tileHeight = 256; 41 | this._maximumLevel = 18; 42 | this._crs = options.crs || 'BD09'; 43 | if (options.crs === 'WGS84') { 44 | let resolutions: number[] = []; 45 | for (let i = 0; i < 19; i++) { 46 | resolutions[i] = 256 * Math.pow(2, 18 - i); 47 | } 48 | this._tilingScheme = new BaiduMercatorTilingScheme({ 49 | resolutions, 50 | rectangleSouthwestInMeters: new Cartesian2( 51 | -20037726.37, 52 | -12474104.17 53 | ), 54 | rectangleNortheastInMeters: new Cartesian2( 55 | 20037726.37, 56 | 12474104.17 57 | ) 58 | }); 59 | } else { 60 | this._tilingScheme = new WebMercatorTilingScheme({ 61 | rectangleSouthwestInMeters: new Cartesian2(-33554054, -33746824), 62 | rectangleNortheastInMeters: new Cartesian2(33554054, 33746824) 63 | }); 64 | } 65 | this._rectangle = this._tilingScheme.rectangle; 66 | this._credit = undefined; 67 | this._style = options.style || 'normal'; 68 | } 69 | 70 | get url() { 71 | return this._url; 72 | } 73 | 74 | get token() { 75 | return this._token; 76 | } 77 | 78 | get tileWidth() { 79 | if (!this.ready) { 80 | throw new DeveloperError( 81 | 'tileWidth must not be called before the imagery provider is ready.' 82 | ); 83 | } 84 | return this._tileWidth; 85 | } 86 | 87 | get tileHeight() { 88 | if (!this.ready) { 89 | throw new DeveloperError( 90 | 'tileHeight must not be called before the imagery provider is ready.' 91 | ); 92 | } 93 | return this._tileHeight; 94 | } 95 | 96 | get maximumLevel() { 97 | if (!this.ready) { 98 | throw new DeveloperError( 99 | 'maximumLevel must not be called before the imagery provider is ready.' 100 | ); 101 | } 102 | return this._maximumLevel; 103 | } 104 | 105 | get minimumLevel() { 106 | if (!this.ready) { 107 | throw new DeveloperError( 108 | 'minimumLevel must not be called before the imagery provider is ready.' 109 | ); 110 | } 111 | return 0; 112 | } 113 | 114 | get tilingScheme() { 115 | if (!this.ready) { 116 | throw new DeveloperError( 117 | 'tilingScheme must not be called before the imagery provider is ready.' 118 | ); 119 | } 120 | return this._tilingScheme; 121 | } 122 | 123 | get rectangle() { 124 | if (!this.ready) { 125 | throw new DeveloperError( 126 | 'rectangle must not be called before the imagery provider is ready.' 127 | ); 128 | } 129 | return this._rectangle; 130 | } 131 | 132 | get ready() { 133 | return !!this._url; 134 | } 135 | 136 | get credit() { 137 | return this._credit; 138 | } 139 | 140 | get hasAlphaChannel() { 141 | return true; 142 | } 143 | 144 | getTileCredits(x: number, y: number, level: number) {} 145 | 146 | requestImage(x: number, y: number, level: number) { 147 | if (!this.ready) { 148 | throw new DeveloperError( 149 | 'requestImage must not be called before the imagery provider is ready.' 150 | ); 151 | } 152 | let xTiles: any = this._tilingScheme.getNumberOfXTilesAtLevel(level); 153 | let yTiles: any = this._tilingScheme.getNumberOfYTilesAtLevel(level); 154 | let url: string = this._url 155 | .replace('{z}', level) 156 | .replace('{s}', String(1)) 157 | .replace('{style}', this._style); 158 | if (this._crs === 'WGS84') { 159 | url = url.replace('{x}', String(x)).replace('{y}', String(-y)); 160 | } else { 161 | url = url 162 | .replace('{x}', String(x - xTiles / 2)) 163 | .replace('{y}', String(yTiles / 2 - y - 1)); 164 | } 165 | // @ts-ignore 166 | return ImageryProvider.loadImage(this, url); 167 | } 168 | } 169 | 170 | export default BaiduImageryProvider; 171 | -------------------------------------------------------------------------------- /src/mock/line/geoJsonline.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "FeatureCollection", 3 | "features": [ 4 | { 5 | "type": "Feature", 6 | "properties": { 7 | "stroke": "#d11010", 8 | "stroke-width": 3, 9 | "stroke-opacity": 0.9 10 | }, 11 | "geometry": { 12 | "type": "LineString", 13 | "coordinates": [ 14 | [ 15 | 120.16433715820311, 16 | 30.276858411864904 17 | ], 18 | [ 19 | 120.15953063964844, 20 | 30.254915457324778 21 | ], 22 | [ 23 | 120.17189025878906, 24 | 30.243052359289663 25 | ], 26 | [ 27 | 120.17326354980469, 28 | 30.235340577517942 29 | ], 30 | [ 31 | 120.19935607910156, 32 | 30.227628190725536 33 | ], 34 | [ 35 | 120.18699645996094, 36 | 30.217541849095714 37 | ], 38 | [ 39 | 120.1636505126953, 40 | 30.21398171687066 41 | ], 42 | [ 43 | 120.17669677734374, 44 | 30.200926796606026 45 | ], 46 | [ 47 | 120.20004272460938, 48 | 30.198552988693212 49 | ], 50 | [ 51 | 120.22476196289061, 52 | 30.200926796606026 53 | ], 54 | [ 55 | 120.22956848144531, 56 | 30.209234673510014 57 | ], 58 | [ 59 | 120.234375, 60 | 30.227628190725536 61 | ], 62 | [ 63 | 120.23574829101562, 64 | 30.240086360983426 65 | ], 66 | [ 67 | 120.23918151855467, 68 | 30.256694798480346 69 | ], 70 | [ 71 | 120.24124145507811, 72 | 30.259660295442085 73 | ], 74 | [ 75 | 120.26046752929688, 76 | 30.259660295442085 77 | ], 78 | [ 79 | 120.26390075683594, 80 | 30.237713497892038 81 | ], 82 | [ 83 | 120.25978088378908, 84 | 30.227628190725536 85 | ], 86 | [ 87 | 120.24742126464844, 88 | 30.184308939305243 89 | ], 90 | [ 91 | 120.2618408203125, 92 | 30.178966889660163 93 | ], 94 | [ 95 | 120.28175354003906, 96 | 30.18846366653094 97 | ], 98 | [ 99 | 120.29891967773438, 100 | 30.22169517385814 101 | ], 102 | [ 103 | 120.29754638671875, 104 | 30.24364554820945 105 | ], 106 | [ 107 | 120.29342651367188, 108 | 30.256694798480346 109 | ], 110 | [ 111 | 120.32501220703125, 112 | 30.217541849095714 113 | ], 114 | [ 115 | 120.31883239746092, 116 | 30.200926796606026 117 | ], 118 | [ 119 | 120.28244018554688, 120 | 30.173624550358536 121 | ], 122 | [ 123 | 120.25978088378908, 124 | 30.157002087161636 125 | ], 126 | [ 127 | 120.21308898925783, 128 | 30.15581466111752 129 | ], 130 | [ 131 | 120.19386291503905, 132 | 30.167094631229592 133 | ], 134 | [ 135 | 120.16914367675781, 136 | 30.177186142075502 137 | ], 138 | [ 139 | 120.15472412109375, 140 | 30.20211367909724 141 | ], 142 | [ 143 | 120.14236450195312, 144 | 30.208641276987787 145 | ], 146 | [ 147 | 120.11833190917967, 148 | 30.170656458930967 149 | ], 150 | [ 151 | 120.12176513671875, 152 | 30.164126343161097 153 | ], 154 | [ 155 | 120.14648437499999, 156 | 30.158189498907962 157 | ] 158 | ] 159 | } 160 | } 161 | ] 162 | } 163 | -------------------------------------------------------------------------------- /src/map/service/CesiumService.ts: -------------------------------------------------------------------------------- 1 | import MapService from '../common/MapService'; 2 | import { CesiumInstanceOptions } from '@/map/type/CesiumType'; 3 | import { BaseMap, LayerImagesEnum, MapTypeEnum, ChangeLayerImageConfig } from '@/map/type/CommonType'; 4 | import CommonStore from '../../map/common/CommonStore'; 5 | import { Viewer, UrlTemplateImageryProvider, Entity, Cartesian3, Rectangle, Camera, Ion, Matrix4, EasingFunction, } from 'cesium'; 6 | import '../service/cesium/imageryProvider/index'; 7 | import { AmapImageryProvider, BaiduImageryProvider, TdtImageryProvider } from '../service/cesium/imageryProvider/index'; 8 | 9 | 10 | export default class CesiumService extends MapService implements BaseMap{ 11 | constructor(props: CesiumInstanceOptions) { 12 | Ion.defaultAccessToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiI4ZTc3YzJkZS03Y2MwLTQxOTMtOGE1OC0yZWI5NjU2MWI4YTEiLCJpZCI6NTgzMTIsImlhdCI6MTYzMTQ0MjY0M30.efQBG7QmD_JweNb9bt8P6-XqJTskjXicS0eiEAbIe2I'; 13 | super(); 14 | } 15 | 16 | /** 17 | * 初始化地图实例 18 | * @param type 19 | * @param props 20 | * @protected 21 | */ 22 | public async initMapInstance(type: MapTypeEnum, props: CesiumInstanceOptions): Promise { 23 | const mapInstanceCache: any = await CommonStore.getInstance('CESIUM'); 24 | console.log(mapInstanceCache); 25 | if (mapInstanceCache) { 26 | return mapInstanceCache; 27 | } 28 | const map: Viewer = new Viewer(props.id, { 29 | ...CesiumService.mergeOptions(props), 30 | }); 31 | CommonStore.setInstance(type, map); 32 | // 启用地球照明 33 | map.scene.globe.enableLighting = !!props.enableLighting; 34 | // 影藏掉底部的logo 35 | const logo: HTMLElement = document.querySelector('.cesium-viewer-bottom') as HTMLElement; 36 | if (logo) { 37 | logo.style.display = 'none'; 38 | } 39 | map.scene.morphTo3D(0.0); //默认三维地图 40 | 41 | //关闭快速抗锯齿,文字清晰 42 | map.scene.postProcessStages.fxaa.enabled = false; 43 | map.scene.highDynamicRange = false; 44 | 45 | //禁止相机入地 46 | map.scene.screenSpaceCameraController.minimumZoomDistance = 2500; //原来是100 47 | (map.scene.screenSpaceCameraController as any)._minimumZoomRate = 30000; //设置相机缩小时的速率 48 | map.clock.onTick.addEventListener(() => { 49 | if (map.camera.pitch > 0) { 50 | map.scene.screenSpaceCameraController.enableTilt = false; 51 | } 52 | }); 53 | return map; 54 | } 55 | 56 | /** 57 | * 修改图层 58 | * @param type 59 | * @param config 60 | * @param instance 61 | */ 62 | public changeLayer(type: LayerImagesEnum, config: ChangeLayerImageConfig, instance: T): T { 63 | switch (type) { 64 | case 'AMAP': 65 | instance.imageryLayers.addImageryProvider(new AmapImageryProvider(config)); 66 | break; 67 | case 'BAIDU': 68 | // @ts-ignore 69 | instance.imageryLayers.addImageryProvider(new BaiduImageryProvider(config)); 70 | break; 71 | case 'TIANDITU': 72 | instance.imageryLayers.addImageryProvider(new TdtImageryProvider(config)); 73 | break; 74 | } 75 | return instance; 76 | 77 | } 78 | 79 | /** 80 | * 渲染html marker 81 | * @param html 82 | * @param instance 83 | */ 84 | public renderHtmlMarker(html: string, instance: T): any { 85 | return null; 86 | } 87 | 88 | /** 89 | * 合并参数 90 | * @param props 91 | * @private 92 | */ 93 | private static mergeOptions(config: CesiumInstanceOptions): CesiumInstanceOptions { 94 | const defaultParams: CesiumInstanceOptions = { 95 | id: config.id, 96 | animation: config.animation || false, 97 | baseLayerPicker: config.baseLayerPicker || false, 98 | fullscreenButton: config.fullscreenButton || false, 99 | vrButton: config.vrButton || false, 100 | geocoder: config.geocoder || false, 101 | homeButton: config.homeButton || false, 102 | infoBox: config.infoBox || false, 103 | sceneModePicker: config.sceneModePicker || false, 104 | selectionIndicator: config.selectionIndicator || false, 105 | timeline: config.timeline || false, 106 | navigationHelpButton: config.navigationHelpButton || false, 107 | scene3DOnly: true, 108 | navigationInstructionsInitiallyVisible: false, 109 | showRenderLoopErrors: false, 110 | imageryProvider: (config.templateImageLayerUrl 111 | ? new UrlTemplateImageryProvider({ 112 | url: config.templateImageLayerUrl, 113 | }) 114 | : null) as UrlTemplateImageryProvider, 115 | }; 116 | return defaultParams; 117 | } 118 | 119 | 120 | /** 121 | * 创建marker 122 | * @param options 123 | */ 124 | public createMarker(options: Entity.ConstructorOptions) { 125 | return new Entity(options); 126 | } 127 | 128 | /** 129 | * 相机飞行 130 | * @param camera 131 | * @param options 132 | */ 133 | public flyTo(camera: Camera, options: { destination: Cartesian3 | Rectangle; orientation?: any; duration?: number; complete?: Camera.FlightCompleteCallback; cancel?: Camera.FlightCancelledCallback; endTransform?: Matrix4; maximumHeight?: number; pitchAdjustHeight?: number; flyOverLongitude?: number; flyOverLongitudeWeight?: number; convert?: boolean; easingFunction?: EasingFunction.Callback; }) { 134 | return camera.flyTo(options); 135 | } 136 | 137 | /** 138 | * 中心视图设置 139 | * @param camera 140 | * @param options 141 | */ 142 | public setView(camera: Camera, options: { destination?: Cartesian3 | Rectangle; orientation?: any; endTransform?: Matrix4; convert?: boolean; }) { 143 | return camera.setView(options); 144 | } 145 | } 146 | -------------------------------------------------------------------------------- /src/mock/popUp/stationList1.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "code": "LYSLJ_RIVER_70102550", 4 | "level": null, 5 | "latitude": "30.265277", 6 | "watershedId": "60601", 7 | "pollutants": [ 8 | { 9 | "overProof": null, 10 | "bstel": 0.0, 11 | "code": "w99030", 12 | "mpFlag": false, 13 | "grade": null, 14 | "name": "", 15 | "value": 0.0 16 | }, 17 | { 18 | "overProof": null, 19 | "bstel": 0.0, 20 | "code": "e01201", 21 | "mpFlag": false, 22 | "grade": null, 23 | "name": "", 24 | "value": 2.26 25 | } 26 | ], 27 | "regionId": "659024", 28 | "controlLevel": "003", 29 | "monitoringMethods": 1, 30 | "accessCode": "LYSLJ_RIVER_70102550", 31 | "name": "三堡船闸外", 32 | "property": null, 33 | "online": 1, 34 | "id": "14224", 35 | "time": "2021-06-30 03:10:00", 36 | "runState": 1, 37 | "mainPollutant": null, 38 | "longitude": "120.221388" 39 | }, 40 | { 41 | "code": "SW7104", 42 | "regionId": "659051", 43 | "controlLevel": "003", 44 | "monitoringMethods": 1, 45 | "latitude": "30.29785", 46 | "accessCode": "SW7104", 47 | "name": "沿山河沈家桥(拱墅区)", 48 | "property": null, 49 | "id": "14225", 50 | "watershedId": "60601", 51 | "longitude": "120.08772" 52 | }, 53 | { 54 | "code": "LYSLJ_RESERVOIR_HZ000089", 55 | "regionId": "330127", 56 | "controlLevel": "003", 57 | "monitoringMethods": 1, 58 | "latitude": "0", 59 | "accessCode": "LYSLJ_RESERVOIR_HZ000089", 60 | "name": "下源水库", 61 | "property": null, 62 | "id": "14226", 63 | "watershedId": "60601", 64 | "longitude": "0" 65 | }, 66 | { 67 | "code": "LYSLJ_RESERVOIR_70116224", 68 | "level": null, 69 | "latitude": "29.955361", 70 | "watershedId": "70708168", 71 | "pollutants": [ 72 | { 73 | "overProof": null, 74 | "bstel": 0.0, 75 | "code": "e01201", 76 | "mpFlag": false, 77 | "grade": null, 78 | "name": "", 79 | "value": 135.82 80 | } 81 | ], 82 | "regionId": "659094", 83 | "controlLevel": "003", 84 | "monitoringMethods": 1, 85 | "accessCode": "LYSLJ_RESERVOIR_70116224", 86 | "name": "渌渚西坞水库", 87 | "property": null, 88 | "online": 1, 89 | "id": "14227", 90 | "time": "2021-06-30 03:10:00", 91 | "runState": 1, 92 | "mainPollutant": null, 93 | "longitude": "119.789778" 94 | }, 95 | { 96 | "code": "SW72123", 97 | "level": null, 98 | "latitude": "0", 99 | "watershedId": "60601", 100 | "pollutants": [ 101 | { 102 | "overProof": null, 103 | "bstel": 0.0, 104 | "code": "e01201", 105 | "mpFlag": false, 106 | "grade": null, 107 | "name": "", 108 | "value": 3.26 109 | } 110 | ], 111 | "regionId": "330109", 112 | "controlLevel": "003", 113 | "monitoringMethods": 1, 114 | "accessCode": "SW72123", 115 | "name": "方千娄(林水)", 116 | "property": null, 117 | "online": 0, 118 | "id": "14228", 119 | "time": "2021-05-05 14:00:00", 120 | "runState": 0, 121 | "mainPollutant": null, 122 | "longitude": "0" 123 | }, 124 | { 125 | "code": "SW69703", 126 | "level": null, 127 | "latitude": "30.3875", 128 | "watershedId": "60601", 129 | "pollutants": [ 130 | { 131 | "overProof": null, 132 | "bstel": 0.0, 133 | "code": "e01201", 134 | "mpFlag": false, 135 | "grade": null, 136 | "name": "", 137 | "value": 3.72 138 | } 139 | ], 140 | "regionId": "659197", 141 | "controlLevel": "003", 142 | "monitoringMethods": 1, 143 | "accessCode": "SW69703", 144 | "name": "潘板(林水)", 145 | "property": null, 146 | "online": 0, 147 | "id": "14230", 148 | "time": "2021-05-07 19:00:00", 149 | "runState": 0, 150 | "mainPollutant": null, 151 | "longitude": "119.8725" 152 | }, 153 | { 154 | "code": "SW7101", 155 | "regionId": "659051", 156 | "controlLevel": "003", 157 | "monitoringMethods": 1, 158 | "latitude": "30.29785", 159 | "accessCode": "SW7101", 160 | "name": "龙山水库(拱墅区)", 161 | "property": null, 162 | "id": "14231", 163 | "watershedId": "60601", 164 | "longitude": "120.08772" 165 | }, 166 | { 167 | "code": "SW7102", 168 | "level": null, 169 | "latitude": "30.29785", 170 | "watershedId": "60601", 171 | "pollutants": [ 172 | { 173 | "overProof": null, 174 | "bstel": 0.0, 175 | "code": "e01201", 176 | "mpFlag": false, 177 | "grade": null, 178 | "name": "", 179 | "value": 1.94 180 | } 181 | ], 182 | "regionId": "659051", 183 | "controlLevel": "003", 184 | "monitoringMethods": 1, 185 | "accessCode": "SW7102", 186 | "name": "上塘河半山桥(拱墅区)", 187 | "property": null, 188 | "online": 0, 189 | "id": "14232", 190 | "time": "2021-05-07 19:00:00", 191 | "runState": 0, 192 | "mainPollutant": null, 193 | "longitude": "120.08772" 194 | } 195 | ] 196 | -------------------------------------------------------------------------------- /public/static/kriging.min.js: -------------------------------------------------------------------------------- 1 | ;eval(function(p,a,c,k,e,r){e=function(c){return(c35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)r[e(c)]=k[c]||e(c);k=[function(e){return r[e]}];e=function(){return'\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p}('9.10.18=B(){w 7.18.1l(1m,E)};9.10.19=B(){w 7.19.1l(1m,E)};9.10.1B=B(){6 i,I;4(i=0,I=0;iy)!=(E[j][1]>y))&&(x<(E[j][0]-E[i][0])*(y-E[i][1])/(E[j][1]-E[i][1])+E[i][0])){c=!c}}w c};6 1D=B(){6 u={};1b=B(c,n){6 i,Z=[0].11(n*n);4(i=0;i=e){e=7.1g(X[j*n+k]);N=j;D=k}}}}}++(d[D]);8(N!=D){4(l=0;l=0;l--)8(c[l]!=a[l]){4(k=0;kb)w a+(c-a)/b;w a+((c-a)/b)*(1.5*(h/b)-0.5*7.F(h/b,3))};u.1G=B(t,x,y,c,d,e){6 f={t:t,x:x,y:y,O:0.0,G:0.0,S:0.0,A:1/3,n:0};1t(c){U"1u":f.P=1q;T;U"1v":f.P=1r;T;U"1w":f.P=1s;T};6 i,j,k,l,n=t.H;6 g=9((n*n-n)/2);4(i=0,k=0;i1h?1h:(n*n-n)/2;6 m=f.G/h;6 o=[0].11(h);6 p=[0].11(h);8(h<1h){4(l=0;l=((n*n-n)/2))T}8(k>0){o[l]/=k;p[l]/=k;l++}}8(l<2)w f}n=l;f.G=o[n-1]-o[0];6 X=[1].11(2*n);6 Y=9(n);6 A=f.A;4(i=0;if[1])f[1]=c[i][j][0];8(c[i][j][1]g[1])g[1]=c[i][j][1]}6 h,16;6 a=9(2),b=9(2);6 l=9(2);6 m=9(2);6 x=7.V((f[1]-f[0])/e);6 y=7.V((g[1]-g[0])/e);6 A=9(x+1);4(i=0;i<=x;i++)A[i]=9(y+1);4(i=0;il[1])l[1]=c[i][j][0];8(c[i][j][1]m[1])m[1]=c[i][j][1]}a[0]=7.1j(((l[0]-((l[0]-f[0])%e))-f[0])/e);a[1]=7.V(((l[1]-((l[1]-f[1])%e))-f[0])/e);b[0]=7.1j(((m[0]-((m[0]-g[0])%e))-g[0])/e);b[1]=7.V(((m[1]-((m[1]-g[1])%e))-g[0])/e);4(j=a[0];j<=a[1];j++)4(k=b[0];k<=b[1];k++){h=f[0]+j*e;16=g[0]+k*e;8(c[i].1n(h,16))A[j][k]=u.1x(h,16,d)}}A.1y=f;A.1z=g;A.17=[d.t.19(),d.t.18()];A.Q=e;w A};u.1L=B(a,b,c){};u.1M=B(a,b,c,d,e){6 f=a.1N("1O");f.1P(0,0,a.Q,a.1k);6 g=[c[1]-c[0],d[1]-d[0],b.17[1]-b.17[0]];6 i,j,x,y,z;6 n=b.H;6 m=b[0].H;6 h=7.V(b.Q*a.Q/(c[1]-c[0]));6 k=7.V(b.Q*a.1k/(d[1]-d[0]));4(i=0;i1.0)z=1.0;f.1S=e[7.1j((e.H-1)*z)];f.1T(7.1A(x-h/2),7.1A(y-k/2),h,k)}};w u}();',62,118,'||||for||var|Math|if|Array|||||||||||||||||||||||return|||||function||icol|this|pow|range|length|sum|ll||kriging_matrix_multiply||irow|nugget|model|width|temp|sill|break|case|ceil|||||prototype|rep|dum|pivinv|else|exp|ytarget|zlim|max|min|false|kriging_matrix_diag|kriging_matrix_add|kriging_matrix_chol|kriging_matrix_chol2inv|kriging_matrix_solve|abs|30|slice|floor|height|apply|null|pip|kriging_matrix_transpose|true|kriging_variogram_gaussian|kriging_variogram_exponential|kriging_variogram_spherical|switch|gaussian|exponential|spherical|predict|xlim|ylim|round|mean|new|kriging|kriging_matrix_scale|sqrt|train|sort|while|variance|grid|contour|plot|getContext|2d|clearRect|undefined|continue|fillStyle|fillRect'.split('|'),0,{})); --------------------------------------------------------------------------------