Files
xj-screen/src/assets/mapUtils/map.ts
T
2024-02-20 13:19:54 +08:00

314 lines
12 KiB
TypeScript

import AMapLoader from '@amap/amap-jsapi-loader';
import china from '/@/assets/lngLat/china.ts';
import chinaInner from '/@/assets/lngLat/chinaInner.ts';
import { createCircle, createIcon, getCenter, getLonLat, typeToIcon } from '/@/assets/mapUtils/commonFun.ts';
import { aircraftContent, alarmIcon } from '/@/components/chinaMap/chinaHooks.ts';
import { isFunction } from '/@/utils/is.ts';
import { Callback, ExtDataType, InitMap, MarkerOption, ResultType } from '/@/assets/mapUtils/mapFunTypes.ts';
import { defaultOption, getZoom, mapKey, mapPlugin } from '/@/assets/mapUtils/mapConstant.ts';
let AMap = null;
export const Map = {
map: null,
overlayGroup: null, // 地图中marker
circleGroup: null, //直升机背景圆
cluster: null, //直升机marker点聚合图层
airMarkerList: [], //直升机markerList
placeSearch: null, //地点查询
marker: null, // 健康终端报警
infoWindow: null, //地图弹窗
/**
* @desc 地图舒适化
* @param el dom元素 id选择器
* @param option 地图配置
*/
initMap({ el, option }: InitMap) {
return new Promise((resolve) => {
AMapLoader.load({
key: mapKey, // 申请好的Web端开发者Key,首次调用 load 时必填
version: '2.0', // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15
plugins: mapPlugin, // 需要使用的的插件列表,如比例尺'AMap.Scale'等
}).then((res) => {
AMap = res;
const { zoom, center, mapStyle } = { ...defaultOption, ...option };
//基本地图加载
this.map = new AMap.Map(el, {
resizeEnable: true,
center: center,
zoom: zoom,
mapStyle: 'amap://styles/' + mapStyle,
version: '2.0',
});
// 异步同时加载多个插件
new AMap.plugin(mapPlugin, () => {
this.drawInnerLine();
this.drawOutLine();
});
resolve();
});
});
} /**
* @desc 中国外层边界线
*/,
drawOutLine() {
let geoJson = new AMap.GeoJSON({
geoJSON: china,
getPolygon: function (geoJson: string, lngLats: any) {
return new AMap.Polyline({
path: lngLats[0],
strokeColor: '#2384dd',
strokeWeight: 3,
// lineJoin: 'round', //折线拐点的绘制样式
isOutline: false,
// borderWeight: 2,
// outlineColor: '#6ccffe',
});
},
});
this.map.add(geoJson);
} /**
* @desc 中国内层边界线
*/,
drawInnerLine() {
let geoJson = new AMap.GeoJSON({
geoJSON: chinaInner,
getPolygon: function (geoJson: string, lngLats: any) {
return new AMap.Polyline({
path: lngLats[0],
// strokeColor: '#57b2f8',
// strokeColor: '#2BA5FF',
// strokeColor: '#3d6eff',
// strokeWeight: 2,
// zIndex: 10,
isOutline: true,
outlineColor: '#2692fc',
borderWeight: 1,
strokeColor: '#88b9f8',
strokeWeight: 1,
strokeOpacity: 0.8,
});
},
});
this.map.add(geoJson);
},
/**
* @desc 设置地图级别与中心点
* @param center 【lon,lat】
* @param zoom 地图层级
* */
setZoomCenter(center, zoom = 12) {
this.map && this.map.setZoomAndCenter(zoom, center);
},
/**
* @desc 清空当前地图上除了边界线的覆盖物
*/
removeOverlayGroup() {
this.clearAircraft();
this.clearOverlay();
this.clearAirRange();
this.clearMarker(); //
if (this.airMarkerList) {
this.airMarkerList = [];
}
this.clearActiveHospital();
this.clearInfoModal();
// this.map.remove(this.airMarkerList);
}, //
/**
* @desc 创建覆盖物组,用于批量处理点 (控制显隐,点击事件等)
* @param result
* @param extData
* @param callback
*/
createOverlay(result: ResultType[], extData?: ExtDataType, callback?: Callback) {
this.removeOverlayGroup();
this.overlayGroup = new AMap.OverlayGroup();
let list = getLonLat(result);
let center = getCenter(list);
let zoom = getZoom(list);
this.setZoomCenter(center, zoom);
for (let i = 0; i < result.length; i++) {
let { type, lon, lat, lng } = result[i];
if (lng) {
lon = lng;
}
if (!lon || !lat || !type) {
continue;
}
// 创建一个 Icon
let startIcon = typeToIcon(type);
// 将 icon 传入 marker
let startMarker = new AMap.Marker({
// 点的坐标
position: [lon, lat], // 指定点的icon,也可以是个url ,但这样就不能对图片进行设置了
icon: startIcon, //启用点击事件 如果需要点击事件,必须开启
clickable: true, //点额外携带的数据,用户自定义属性,支持JavaScript API任意数据类型
offset: [-18, -32],
maxZoom: 14,
extData: result[i],
label: {
content: isFunction(extData?.content) && extData?.content(result[i]),
},
...extData?.extOption,
});
// 可以调用setExtData()设置自定义属性
//将组 挂载到地图上
this.overlayGroup.setMap(this.map);
//将需要批量控制的点放到一个组中,通过控制组,就可以操作组内所有所有覆盖物
this.overlayGroup.addOverlay(startMarker);
}
this.overlayGroup.on('click', function (e) {
//拿到点中携带的数据
if (!isFunction(callback)) return;
callback(e.target.getExtData());
});
},
clearOverlay() {
if (this.overlayGroup) {
this.map.remove(this.overlayGroup);
this.overlayGroup.setMap(null);
this.overlayGroup = null;
}
},
/**
* @desc 创建直升机marker
* @param result
*/
createAircraft(result: ResultType[]) {
this.removeOverlayGroup();
this.clearActiveHospital();
// debugger;
if (!Array.isArray(result) && result.length == 0) return;
this.createAirRange(result);
let that = this;
let arr = result.map((item) => ({ weight: 4, lnglat: [item.lon, item.lat], params: item.name }));
let count = 4;
this.cluster = new AMap.MarkerClusterer(
that.map, // 地图实例
arr,
{
renderMarker: (context) => {
let factor = Math.pow(context.count / count, 1 / 18);
let div = document.createElement('div');
div.className = 'render-air';
let Hue = 180 - factor * 180;
let size = Math.round(30 + Math.pow(context.count / count, 1 / 5) * 20);
div.style.width = div.style.height = size + 'px';
div.innerHTML = aircraftContent() || context.count;
div.style.color = '#fff';
div.style.fontSize = '14px';
context.marker.setOffset(new AMap.Pixel(-size / 2, -size / 2));
context.marker.setContent(div);
// this.airMarkerList.push(context.marker);
// context.marker.on('click', () => {
// console.log('data', context);
// });
},
}
);
// this.cluster.setMap(this.map);
},
clearAircraft() {
if (this.cluster) {
this.cluster.setMap(null);
// this.map.remove(this.cluster);
// this.cluster = null;
}
} /**
* @desc 飞机范围
* @param list
*/,
createAirRange(list: ResultType[]) {
this.removeOverlayGroup();
this.circleGroup = new AMap.OverlayGroup();
for (let i = 0; i < list.length; i++) {
let circle = createCircle({ lon: list[i].lon, lat: list[i].lat });
this.circleGroup.setMap(this.map);
this.circleGroup.addOverlay(circle);
}
},
clearAirRange() {
if (this.circleGroup) {
this.map.remove(this.circleGroup);
this.circleGroup = null;
}
} /**
* @desc 地方医院医疗点显示
* @param cityCode 城市code
* @param keywords 搜索名称
*/,
createActiveHospital(cityCode: string, keywords = '医院') {
this.removeOverlayGroup();
this.clearActiveHospital();
if (!cityCode) return;
if (!this.placeSearch) {
this.placeSearch = new AMap.PlaceSearch({
pageSize: 30, // 单页显示结果条数
pageIndex: 1, // 页码
city: cityCode, // 兴趣点城市
citylimit: true, //是否强制限制在设置的城市内搜索
map: this.map, // 展现结果的地图实例
// panel: 'map_hospital', // 结果列表将在此容器中进行展示。
autoFitView: false, // 是否自动调整地图视野使绘制的 Marker点都处于视口的可见范围
});
}
this.placeSearch.setCity(cityCode);
//关键字查询
this.placeSearch.search(keywords);
},
clearActiveHospital() {
if (this.placeSearch) {
this.placeSearch.clear();
}
},
createMarker(option: MarkerOption, callbck?: Callback) {
this.clearMarker();
let { lon, lat, zoom = 12 } = option;
const icon = createIcon({ icon: alarmIcon, iconSize: [36, 42], imageSize: [36, 42] });
let str = option?.realName && option?.eventType_dictText ? `${option?.realName},${option?.eventType_dictText}` : `${option?.realName}`;
this.marker = new AMap.Marker({
position: [lon, lat],
icon: icon,
offset: new AMap.Pixel(0, 0), //设置偏移量
label: {
content: `<div class="alarm-content" >
<div>${str}</div>
</div>`,
offset: new AMap.Pixel(0, -9),
direction: 'top',
},
});
this.map.add(this.marker);
this.map.setZoomAndCenter(zoom, [lon, lat]);
this.marker.on('click', callbck);
},
clearMarker() {
if (this.marker) {
this.marker?.setMap(null);
this.marker = null;
}
},
/**
* @desc 创建地图详情弹窗
*
* */
createInfoModal({ option, content }) {
let { lat, lng } = option;
this.infoWindow = new AMap.InfoWindow({
position: [lng, lat],
offset: new AMap.Pixel(-5, -25),
content: content,
closeWhenClickMap: true,
});
this.infoWindow.open(this.map);
},
clearInfoModal() {
if (this.infoWindow) {
this.infoWindow?.setMap(null);
this.infoWindow = null;
}
},
};