业务场景:需要在高德地图上加载地块数据并灵活切换。
效果图:8000多地块加载使用了2.几秒且无卡顿现象
最开始使用的是将边界信息用AMap.Polygon
绘制到地图上,发现界面会卡顿,通过Promise去异步加载并递归调用渲染,情况好了些但是加载速度久了很多,用户体验不是很好,最后使用了他的2.0版本Loca,话不多说直接上代码:
首先咱们得初始化地图:
import AMapLoader from "@amap/amap-jsapi-loader"; //引用高德
let mapLand; //声明地图对象
var loca = ""; //声明loca
let fillColor = "blue"; //默认
let strokeColor = "red"; //默认
let fillOpacity = 0.1; //默认
const riskType = ["类型A", "类型B", "类型C", "类型D"];
onMounted(() => {
//初始化地图
LoadMap();
//我这里是暴露出来的,不暴露可以不写
window.mapStore = mapStore;
});
//初始化地图
function LoadMap() {
AMapLoader.load({
key: "", // 申请好的Web端开发者Key,首次调用 load 时必填
version: "2.0", // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15
plugins: ["Amap.Geocoder"], // 需要使用的的插件列表,如比例尺'AMap.Scale'等
AMapUI: {
version: "1.1", // AMapUI 缺省 1.1
plugins: ["overlay/SimpleMarker"], // 需要加载的 AMapUI ui插件
},
Loca: {
version: "2.0.0", //版本 此处需要填写!
},
}).then((AMap) => {
mapLand = new AMap.Map("map", {
mapStyle: "", //地图样式 自行修改
pitch: 40,
center: [121.538319, 31.153452],
zoom: 13,
fitView: true,
viewMode: "2D",
zIndex: 100,
});
loca = new Loca.Container({
map: mapLand,
});
//地块数据
LoadLandDataXYs();
});
}
接下来就是读取渲染数据:
//查询数据集合
async function LoadLandDataXYs() {
await proxy.$request.get("你的接口url").then((res) => {
if (res.data.code == 200) {
changeXyToGeoJSON(res.data.result);
}
});
}
//地理坐标数据分类处理
var LandType = {};
function changeXyToGeoJSON(data) {
data.forEach((gg) => {
if (AreaNiCheng.landColor.hasOwnProperty(gg.landType)) {
if (!LandType.hasOwnProperty(gg.landType)) {
LandType[gg.landType] = [];
}
LandType[gg.landType].push(gg);
if (!LandType.hasOwnProperty(gg.riskLevel)) {
LandType[gg.riskLevel] = [];
}
LandType[gg.riskLevel].push(gg);
}
});
for (let key in LandType) {
setTimeout(() => {
if (riskType.find((ff) => ff == key) == null) {
ForDataChange(
LandType[key],
riskType.find((ff) => ff == key) != null ? "类型1" : "类型2",
key
);
}
}, 500);
}
}
//将数据处理成GeoJSON
function ForDataChange(loadD, riskType, key) {
let GeoJSON = [];
loadD.forEach((e) => {
let totalArea = [];
e.areaPoints.forEach((ff) => {
totalArea.push([ff.longitude, ff.latitude]);
});
GeoJSON.push({
type: "Feature",
//这里你需要什么属性都可以在此写入
properties: {
name: e.idNum,
risk: e.riskLevel,
landType: e.landType,
landId: e.id,
//……
},
geometry: {
type: "Polygon",
coordinates: [totalArea],
},
});
});
ShowMapData(GeoJSON, riskType, key);
}
//渲染数据
function ShowMapData(geoFeatures, type = null, key = null) {
var geo = new Loca.GeoJSONSource({
data: {
type: "FeatureCollection",
features: geoFeatures,
},
});
//这里主要是给图斑赋值颜色
if (type == "类型1" || type == "类型2") {
if (AreaNiCheng.landColor.hasOwnProperty(key)) {
fillColor = AreaNiCheng.landColor[key];
strokeColor = AreaNiCheng.landColor[key];
} else {
fillColor = AreaNiCheng.landColor["另外"];
strokeColor = AreaNiCheng.landColor["另外"];
}
} else if (type == "村") {
fillColor = AreaNiCheng.landColor["村区域"];
strokeColor = AreaNiCheng.landColor["村区域"];
}
var pl = new Loca.PolygonLayer({
loca,
strokeOpacity: fillOpacity,
zIndex: type == "xxx" ? 5 : 500,
visible: key == "xxx" ? false : true, //默认隐藏、显示
});
pl.setSource(geo);
pl.setStyle({
topColor: (index, feature) => {
return strokeColor;
},
sideTopColor: (index, feature) => {
return strokeColor;
},
});
//地图点击事件
mapLand.on("click", function (e) {
var feat = pl.queryFeature(e.pixel.toArray());
if (feat != null) {
// console.log(feat)
}
});
loca.add(pl);
// 设置样式
pl.setStyle({
radius: 30,
fillOpacity: fillOpacity,
borderWidth: 10,
topColor: type == "xxx" ? [255, 255, 0, 0.01] : strokeColor,
});
pl.render();
var thisKey = `${type}-${key}`;
if (!mapStore.controlGroup.hasOwnProperty(thisKey)) {
mapStore.controlGroup[thisKey] = [];
}
//这里主要是在给不同类型的地块分组,方便后面切换
switch (key) {
case "xx":
overlayGroupCbyd = overlayGroupHelperNew(pl);
mapStore.controlGroup[thisKey].push(overlayGroupCbyd);
break;
case "xx":
overlayGroupDz = overlayGroupHelperNew(pl);
mapStore.controlGroup[thisKey].push(overlayGroupDz);
break;
case "xx":
overlayGroupDc = overlayGroupHelperNew(pl);
mapStore.controlGroup[thisKey].push(overlayGroupDc);
break;
//……
}
}
//封装地图切换展示方法
function overlayGroupHelperNew(data) {
return {
arr: data,
show: function () {
data.show();
},
hide: function () {
data.hide();
},
};
}
最后是切换类型,基本上加载完成后秒切:
//切换show or hide
function ShowOrHideMapElementFunNew(type, classes = null) {
for (let key in window.mapStore.controlGroup) {
//展示全量
if (classes == null) {
if (type == "??") {
if (key.indexOf("??") >= 0) {
window.mapStore.controlGroup[key][0].show();
} else {
window.mapStore.controlGroup[key][0].hide();
}
} else {
if (key.indexOf("风险") >= 0 && key.indexOf("??")<0) {
window.mapStore.controlGroup[key][0].show();
} else {
window.mapStore.controlGroup[key][0].hide();
}
}
}
//展示选择的类型 其余全部隐藏
else {
if (type == "XX") {
if (key.indexOf("XX") <= -1) {
if (key.indexOf(classes) >= 0) {
window.mapStore.controlGroup[key][0].show();
} else {
window.mapStore.controlGroup[key][0].hide();
}
}
} else {
if (key.indexOf("XX") <= -1) {
if (key.indexOf(classes) >= 0) {
mapStore.controlGroup[key][0].show();
} else {
mapStore.controlGroup[key][0].hide();
}
}
}
}
}
}
如有不好的地方,请大佬们多多指教!