import { AutocompleteSearch, AutocompleteSearchCallback, AutocompleteSelect, AutocompleteSelectCallback, ClickOptions, DrivingSearchCallback, EventCallback, HtmlRender, IAutocomplete, ICircle, IDriving, IInfoWindow, ILayer, ILngLat, IMap, IMapOptions, IMarker, IMarkerCluster, IMarkOptions, IMouseTool, IPixel, IPlaceSearch, IRenderClusterMarker, ISelf, ITileLayer, MarkerClusterCallback, PixelRender, PlaceSearchCallback } from './map' import { SearchDownList } from './component/SearchDownListPlugins/SearchDownList'; import { SearchService } from '@src/app/searchComponent.service'; import { HttpClient } from '@angular/common/http'; import * as ObjectID from 'bson-objectid'; import * as global from 'globals'; declare var KMap: any; class KedaBasic implements ISelf { self: any; discriminator: string = "ISelf"; } const cityPosition: number[] = [108.2854170, 22.8616262]; //广西壮族自治区 坐标 const beforCity: string = "广西壮族自治区"; //当前城市 const cityCode: string = "450000"; //当前城市 行政编码 export class KeDaMap extends KedaBasic implements IMap { public isLoadEnd:boolean = false public LoadedCallback:Function[] = []; constructor(container: string, options: IMapOptions) { //地图初始化 super(); let that = this let opt = Object.assign({}, { containerId: container }, options) as any; opt.configUrl = "/assets/kmap/Kmap.config.json"; opt.targetCoordinateType = "WGS84"; opt.center = cityPosition; opt.zoom === undefined ? opt.zoom = 9 : opt.zoom = opt.zoom - 2 if (opt.mapStyle && opt.mapStyle == 'amap://styles/grey') { opt.solution = '8888' } let mapLayer = function () { if (opt.viewMode && opt.viewMode == "3D") { let data = { type: 'FeatureCollection', features: [ { type: 'Feature', geometry: { type: 'Point', coordinates: cityPosition }, properties: { height: 30 } } ] }; that.self.add3DLayer({ data: data }); } that.isLoadEnd = true that.LoadedCallback.forEach(i=>{ try{ i(); }catch(e) { console.log(e,'错误') } }); that.LoadedCallback = [] } opt.onLoadMap = mapLayer this.self = new KMap(opt); } containerToLngLat(e: IPixel): ILngLat { let d = null; this.self.getGeoPointByPixel({ ePoint: e.self, callback: (e) => { d = new KeDaLngLat(e.data.lng, e.data.lat); } }) return d; } setAdministrativeAreaStyle(component: any, getData?: Function, setData?: Function) { //自定义 行政区划 样式 let _this =this; if(!this.isLoadEnd){ this.LoadedCallback.push( ()=>_this.setAdministrativeAreaStyle(component,getData,setData) ); return; } let beforeCode:string = cityCode //当前 城市行政编码 let setTime //延时器 let initMap = ()=>{ //绘制地图 this.self.getGeometryByAdminCode({ code: beforeCode, callback: (res)=> { this.self.highlightPolygon({ color: 'rgba(0,102,255,0.5)', area: res.data }); } }); } //function let clickMap = (e)=>{ //点击地图 _this.self.getAdminInfoByPoint({ point: [e.lnglat.lng, e.lnglat.lat], callback: (res)=>{ if (res.status === 10) { console.log(res.data,'当前点击行政区域') if (res.data.adminId != beforeCode && res.data.parentId == cityCode) { //当前点击位置已改动 _this.self.clear() window.clearTimeout(setTime) beforeCode = (res.data.adminId).toString() setTime = window.setTimeout(()=>{ initMap() },100) let name = { properties:{name: res.data.nameZh } } getData && getData.call(component,name); return } else if (res.data.parentId != cityCode) { _this.self.clear() window.clearTimeout(setTime) beforeCode = cityCode setTime = window.setTimeout(()=>{ initMap() },100) setData && setData.call(component); } } else { if (beforeCode != cityCode) { _this.self.clear() window.clearTimeout(setTime) beforeCode = cityCode setTime = window.setTimeout(()=>{ initMap() },100) setData && setData.call(component); } } } }); } initMap() let level = Number(sessionStorage.getItem("level")) if (level < 3) { this.on("click",clickMap,this); } } clearMap() { this.self.clear() } distance(a: number[], b: number[]) { let num this.self.distancePoints({ startPoint: a, endPoint: b, units: "meters", callback: (res) => { num = res.data } }) return num } setZoomAndCenter(zoom: number, pos: number[]) { this.self.flyTo({ zoom: zoom, point: pos, }); } getBounds() { let bounds = { northEast: null, southWest: null } this.self.getBounds({ callback: (res) => { bounds.northEast = new KeDaLngLat(res.data[0][0],res.data[0][1]) bounds.southWest = new KeDaLngLat(res.data[1][0],res.data[1][1]) } }) return bounds } add(obj: any) { let _this =this; if(!this.isLoadEnd){ this.LoadedCallback.push( ()=>_this.add(obj) ); return; } if (obj && obj.typeName === "KeDaMarker") { let _marker = (obj as KeDaMarker); _marker.map = this; this.self.addCustomOverlay(_marker.self) } else if (obj == "卫星图层") { this.self.setImageLayer({ display: true }) } else if (obj == "路网图层") { this.self.setMapStyle({ solution: '8888' }); } } remove(obj: any) { if (obj && obj.typeName === "KeDaMarker") { obj.KedaMarkerID && this.self.removeCustomOverlayById({ id: obj.KedaMarkerID }) } else if (obj && obj.typeName === "KeDaInfoWindow") { this.self.removeAllPopups() } else if (obj && obj.typeName === "KeDaCircle") { obj.id && this.self.removeLayer({ layerId: obj.id }) } else if (obj == "卫星图层") { this.self.setImageLayer({ display: false }) } else if (obj == "路网图层") { this.self.setMapStyle({ solution: '9999' }); } } setCity(city: string) { let that = this if (city.includes("广西壮族自治区") && this.isLoadEnd) { that.self.flyTo({ zoom: 9, point: cityPosition }); } } getCity(callback: Function) { let autoOptions = { city: "广西壮族自治区" } return callback(autoOptions) } setZoom(zoom: number) { this.self.zoomTo({ zoom: zoom }); } getZoom(): number { let num this.self.getZoom({ callback: (e) => { num = e.data; } }) return num } setCenter(pos: number[] | ILngLat) { let _this =this; if(!this.isLoadEnd){ this.LoadedCallback.push( ()=>_this.setCenter(pos) ); return; } let position = [] if (pos instanceof Array) { position = pos } else { position = pos.getArray(); } this.self.flyTo({ point: position }) } getCenter() { let center this.self.getCenter({ callback: function (res) { center = res.data } }); return center } on(eventName: string, callback: EventCallback, component?: any) { let _this =this; if(!this.isLoadEnd){ this.LoadedCallback.push( ()=>_this.on(eventName,callback,component) ); return; } let eventMapProfile = { complete: "load", click: "click", rightclick: "contextmenu" }; if (eventName == "click") { this.self.addEventOnMap({event: "click", handler: (res)=>{ let event = { lnglat: new KeDaLngLat(res.lngLat.lng,res.lngLat.lat), pixel: new KeDaPixel(res.point.x,res.point.y), type: res.type, target: { id:null } //TODO } callback.call(component,event); } }); } else if (eventName == "complete") { callback.call(component,null); } else { this.self.addEventOnMap({ event: eventMapProfile[eventName], handler: callback }); } } } export class KeDaPixel extends KedaBasic implements IPixel { constructor(x: number, y: number) { super(); this.x = x; this.y = y; this.self = [x, y]; } getArray(): number[] { return this.self; } x: number; y: number; } export class KeDaMarker extends KedaBasic implements IMarker { public map: KeDaMap; public KedaMarkerID:String; public typeName: string = "KeDaMarker"; private html:string = '' constructor(options: IMarkOptions) { super(); let pos = [] if (options.position instanceof Array) { pos = options.position } else { pos = options.position.getArray() } let elementHtml = document.createElement('div') elementHtml.innerHTML = options.content? options.content : this.html let marker = { point: pos, //anchor: 'bottom', //TODO //offset: options.offset? options.offset.self : [0,0], //TODO element: elementHtml.firstElementChild, ended: (res) => { this.KedaMarkerID = res.data; if (options.draggable) { //启用拖拽功能 this.map.self.setCustomOverlayDraggable({ id: this.KedaMarkerID, draggable: true, }) this.map.self.addEventOnCustomOverlays({ selector: `#${this.KedaMarkerID}`, event: 'dragend', }); } this.startBindEvent(); } }; this.self = marker; this._position = pos if (options.map) { this.map = options.map as KeDaMap this.map.self.addCustomOverlay(this.self); } } getLngLatByMarkerEvent(map:IMap,e: any): ILngLat { return e.lnglat; } _position: number[]; setContent(html: string) { //marker 添加 DOM元素 this.map.self.setCustomOverlayProperty({ type: 'id', id: this.KedaMarkerID, element: html, }) } setPosition(x: ILngLat | number[]) { x = (x as ILngLat).getArray == undefined ? x : (x as ILngLat).getArray(); this.map.self.setCustomOverlayProperty({ type: 'id', id: this.KedaMarkerID, point: x }) } setMap() { this.map.self.removeCustomOverlayById({ id: this.KedaMarkerID }) } get id(): string { return this.self.id } set id(str: string) { this.self.id = str } public bindObj = []; // event on(eventName: string, callback: EventCallback, component?: any) { this.bindObj.push({ eventName: eventName, callback: callback, component: component, }); this.startBindEvent(); } startBindEvent() { let _this =this; if (this.map !== undefined) { this.bindObj.forEach((item, index) => { if (item.eventName.includes('drag')) { this.map.self.setCustomOverlayDraggable({ id: this.KedaMarkerID, draggable: true, }) } this.map.self.addEventOnCustomOverlays({ selector: `#${this.KedaMarkerID}`, event: item.eventName, handler: (res) =>{ this.map.self.getOverlayById({ id: this.KedaMarkerID, callback: (p)=>{ let point = p.data.point; let event if (res.lngLat!=undefined && res.point!=undefined) { event = { lnglat: new KeDaLngLat(point.lng,point.lat), pixel: [0,0],//科达覆盖物所用的div坐标为center,儿我们的div正好近似正方形,所以不用偏移 type: res.type, target: { id:this.self.id || null }, _target:res.target } } else { event = { lnglat: new KeDaLngLat(point.lng,point.lat), target: { id:this.self.id || null } } } item.callback.call(item.component,event) } }) } }); }) this.bindObj = []; } } } export class KeDaLngLat extends KedaBasic implements ILngLat { constructor(lng: number, lat: number) { super(); this.lng = lng this.lat = lat this.self = this; } offset(x: number, y: number): ILngLat { return x = 2 * Math.asin(Math.sin(Math.round(x) / 12756274) / Math.cos(this.kT * Math.PI / 180)), x = this.KL + 180 * x / Math.PI, y = 2 * Math.asin(Math.round(y) / 12756274), new KeDaLngLat(x, y); } typeName = "LngLat"; lng: number; lat: number; get KL(): number { return this.lng; } get kT(): number { return this.lat; } getArray(): number[] { return [this.lng, this.lat]; } } export class KedaDriving extends KedaBasic implements IDriving { //路线导航 public map: KeDaMap; public policy: number = 0; // 0:快捷模式, 4:躲避拥堵 public id: string; constructor(options: any) { super(); this.map = options.map as KeDaMap options.policy === undefined ? this.policy = 0 : this.policy = options.policy } search(component: any, posStart: ILngLat, posEnd: ILngLat, callback: DrivingSearchCallback) { let params = { startPoint: posStart.getArray(), endPoint: posEnd.getArray(), error: () => { alert('路线规划失败!') }, ended: (res) => { console.log(res.data,'路径规划') this.id = res.data let router = { routes:[] } callback.call(component,'complete',router) } } if (this.map.isLoadEnd) { //map加载完毕 if (this.policy === 0) { //快捷模式 this.map.self.createMinDistanceRoutePlanning(params) } else { //躲避拥堵 this.map.self.createMinTimeRoutePlanning(params) } } else { let _this =this; this.map.LoadedCallback.push( ()=>_this.search(component,posStart,posEnd,callback) ); } } clear() { this.id? this.map.self.removeRoutePlanning({ id: this.id }) : null } } export class KedaAutocomplete extends KedaBasic implements IAutocomplete { //Autocomplete 关键字搜索 private component: any; private searchDownList: SearchDownList; private $input: any; constructor(options: any, component: any) { super(); this.component = component if (options && options.input != undefined) { //绑定input框 搜索事件 this.searchDownList = global.injector.get(SearchService).appendComponentToBody(SearchDownList).instance; this.$input = document.getElementById(options.input); this.searchDownList.init(this.$input) this.$input.oninput = (e) =>{ //监听 input事件 (this.component.map as KeDaMap).self.queryInfoByType({ code: cityCode, keyword: this.$input.value, maxCount: 10, searchType: [], callback: (res) => { let list = res.data this.searchDownList.searchList = list || [] } }) // search } } } on(eventName: string, callback: AutocompleteSelectCallback) { this.searchDownList.setClickHander((e:any) => { let a = { id : e.id, name : e.name, adcode : e.adminId, district : e.address, location : new KeDaLngLat(e.locationpoint[0],e.locationpoint[1]), type : 'point', poi: { location : new KeDaLngLat(e.locationpoint[0],e.locationpoint[1]) } } callback.call(this.component,a); }); } search(address: string, callback: AutocompleteSearchCallback) { (this.component.map as KeDaMap).self.queryInfoByType({ code: cityCode, keyword: address, maxCount: 10, searchType: [], callback: (res:any) => { let list = { tips:[] }; res.data.forEach(item => { let a = { id : item.id, name : item.name, adcode : item.adminId, district : item.address, location : new KeDaLngLat(item.locationpoint[0],item.locationpoint[1]), type : 'point', poi: { location : new KeDaLngLat(item.locationpoint[0],item.locationpoint[1]) } } list.tips.push(a); }); callback.call(this.component,'complete',list); } }) } } export class KedaPlaceSearch extends KedaBasic implements IPlaceSearch { //PlaceSearch 关键字搜索 private component: any constructor(component: any) { super(); this.component = component } search(address: string, callback: PlaceSearchCallback) { (this.component.map as KeDaMap).self.queryInfoByType({ code: cityCode, keyword: address, maxCount: 10, searchType: [], callback: (res:any) => { let list = { info:'OK', poiList:{ posi:[] } }; res.data.forEach(item => { let a = { id : item.id, name : item.name, adcode : item.adminId, district : item.address, location : new KeDaLngLat(item.locationpoint[0],item.locationpoint[1]), type : 'point', poi: { location : new KeDaLngLat(item.locationpoint[0],item.locationpoint[1]) } } list.poiList.posi.push(a); }); callback.call(this.component,'complete',list); } }) } } export class KedaCircle extends KedaBasic implements ICircle { //圆形 图层 public typeName: string = "KeDaCircle"; public id: string; constructor(options: any) { super(); let circle = { data: { type: 'FeatureCollection', features: [ { type: 'Feature', geometry: { type: 'Point', coordinates: cityPosition }, properties: { id: ObjectID.default.generate() } } ] }, defaultStyles: { "line-dasharray": options.strokeDasharray, "line-opacity": options.strokeOpacity, "fill-color": options.fillColor, "fill-opacity": options.fillOpacity, }, radius: 0, draggable: false, updateHandler: (res) => { }, end: (res) => { this.id = res } } this.self = circle } setRadius(num: number) { //设置圆的半径 this.self.radius = num / 1000 } setCenter(pos: number[]) {//设置圆的中心 this.self.center = pos } setMap(map: KeDaMap) {//把圆添加到 map if (map.isLoadEnd) { this.self.radius != 0 && map.self.addGeometryCircleLayer(this.self) } else { let _this =this; map.LoadedCallback.push( ()=>_this.setMap(map) ); } } } export class KedaMarkerCluster extends KedaBasic implements IMarkerCluster { //Marker 聚合物 public map:KeDaMap public id:string private LoadedCallback:Function[] = [] public markerList:any[] = [] constructor(map: IMap, list: Object[], options: any) { super(); this.map = map as KeDaMap; list.forEach((item:any)=>{ let elementHtml = document.createElement('div') elementHtml.innerHTML = `` let marker = { point: item.lnglat, element: elementHtml.firstElementChild, customProps: item.data, } this.markerList.push(marker) }) if (this.markerList.length) { //有聚合物时 } // let http:HttpClient = global.injector.get(HttpClient) // http.get(`http://10.14.183.81/kiop-web/static/autoGroup/2.19.0.kd/assets/json/buildData.json`).subscribe(data=>{ // console.log(data) // }) //覆盖物聚合 // this.map.self.addOverlayLayer({ // serviceName: 'service_tzn_test3', //业务图层类型 // clustered: true, //是否聚合 // defaultIcon: 'icon-policeman-1',//雪碧图名称 // clusteredMarkerTemplate: `'
' + // '{{IMGTAG}}' +
`, // singleMarkerTemplate: { // default: '
' + // '{{IMGTAG}}' + '
', // filters: [ // { // template: '
' + // '{{IMGTAG}}' + // '
', // icon: 'icon-policeman-1', // //status === 1 的数据,将显示为markerHtml的marker样式 // match: [{ // key: 'status', // value: 1 // }] // }, // ] // }, // ended: function (res) { // console.log(res,'覆盖物聚合·') // this.id = res.data // this.LoadedCallback.forEach(i=>{ // try{ // i(); // }catch(e) { // console.log(e,'错误') // } // }); // this.LoadedCallback = [] // } // }) } setMaxZoom(zoom: number) { throw new Error('Method not implemented.'); } on(eventName: string, callback: MarkerClusterCallback, component?: any): void { let _this =this; if(!this.id){ this.LoadedCallback.push( ()=>_this.on(eventName,callback,component) ); return; } } setData(list: any[]) { if (!list.length && this.id) { } } } export class KedaRenderClusterMarkerr extends KedaBasic implements IRenderClusterMarker { //Marker 聚合物 配置项 discriminator: string = "ISelfCombine"; constructor() { super(); } getFirstImages(context: any): string { return context.data[0].image; } contentRender: HtmlRender; contentNonRender: HtmlRender; pixelRender: PixelRender; pixelNonRender: PixelRender; } export class KedaInfoWindow extends KedaBasic implements IInfoWindow { //信息窗体 public typeName: string = "KeDaInfoWindow"; constructor(options) { super(); let opt = { htmlText: options.content, // offset: options.offset.self, anchor: 'bottom', point: options.position, closeButton: true, } this.self = opt } open(map: IMap) { map.self.addPopup(this.self); } listen(html: any, event: string, callback: Function) { html.addEventListener(event, callback) } } export class KedaLayer extends KedaBasic implements ILayer { //mapInit 配置项 constructor(options: any) { super(); } } export class KedaTileLayer extends KedaBasic implements ITileLayer { //图层切换 constructor() { super(); } Satellite() { //卫星图层 return "卫星图层" } RoadNet() { //路网图层 return "路网图层" } } export class KedaMouseTool extends KedaBasic implements IMouseTool { //地图工具 constructor(map: IMap) { super(); this.self = map.self } layerIds = []; layerIdAreas = []; rule(options: any) { let that = this this.self.measureDistance({ units: 'kilometers', callback: (result) => { var startText, sClass = that.self.mapType === 'AG' ? 'ag-popup-tools' : 'mm-popup-tools'; var result = result.data; if (!result.isEnd) { if (result.isStart) { that.self.addTexts({ points: [{ point: result.point, htmlText: '起点', class: sClass }], anchor: 'left', ended: function (res) { that.layerIds.push(res.data); startText = res.data; } }); } else { that.self.addTexts({ points: [{ point: result.point, htmlText: result.distance.toFixed(4) + 'km', class: sClass }], anchor: 'left', ended: function (res) { that.layerIds.push(res.data); } }); } } else { if (result.index >= 1) { if (result.isFailure) { that.layerIds.forEach((layerId) => { that.self.removeTextsByType({ textType: layerId }); }); return; } that.layerIds.push(result.layerId); if (that.self.mapType === 'BM') { that.self.addTexts({ points: [{ point: result.point, htmlText: '总距离:' + result.distance.toFixed(4) + 'km', class: sClass }], anchor: 'left', ended: function (res) { that.layerIds.push(res.data); } }); } } else { that.layerIds.forEach((layerId) => { that.self.removeTextsByType({ textType: layerId }); }); } } } }); } measureArea(options: any) { let that = this this.self.measureArea({ units: 'meters', callback: (result) => { var sClass = that.self.mapType === 'AG' ? 'ag-popup-tools' : 'mm-popup-tools'; var result = result.data; if (!result.isEnd) { if (result.index >= 2) { that.self.addTexts({ points: [{ point: result.point, htmlText: result.area + '平方米', class: sClass }], anchor: 'left', ended: function (res) { that.layerIdAreas.push(res.data); } }); } } else { if (result.index >= 2) { if (result.isFailure) { that.layerIdAreas.forEach((layerId) => { that.self.removeTextsByType({ textType: layerId }); }); return; } that.layerIdAreas.push(result.layerId); if (that.self.mapType === 'BM') { that.self.addTexts({ points: [{ point: result.point, htmlText: '总面积:' + result.area + '平方米', class: sClass }], anchor: 'left', ended: function (res) { that.layerIdAreas.push(res.data); } }); } } } } }); } close(isTrue: boolean) { if (isTrue) { this.self.clear(); for (var i in this.layerIds) { this.self.removeTextsByType({ textType: this.layerIds[i] }); } for (var i in this.layerIdAreas) { this.self.removeTextsByType({ textType: this.layerIdAreas[i] }); } this.layerIdAreas = []; this.layerIds = []; } } }