做成的效果为: 规划路线时可在地图添加起始点, 终点, 途径点
主要逻辑是通过一个数组记录每个点所在的图层, 然后点击增删图标来实现对对应图标的新增删除.
问题
因为平常一般都是用响应式数据, 所以把数组定义成ref([]). 新增图标时没什么问题, 但是当删除某个图标后, 进行地图缩放时后面的图标直接乱跑, 并且控制台报错chunk-6WXMTNSE.js?v=11499401:5166 Uncaught TypeError: Cannot read properties of null (reading '_latLngToNewLayerPoint'). 这个错误一般是对已经移除的图层进行操作是才会出现, 排查时发现从ref([])中取出的对象是Proxy(NewClass), 怀疑是响应式数据的原因, 最后改成使用普通数组后解决.
部分代码如下:
定义参数
const routePoints = ref([]);
let layerArray = []
const mapRef = ref()
let mapInstance // 地图实例
删除某个途径点方法
// 删除途径点
function removeRoutePoint(index) {
let layer = layerArray[index];
if(layer && mapInstance.hasLayer(layer)) {
mapInstance.removeLayer(layer)
}
layerArray.splice(index, 1)
routePoints.value.splice(index, 1)
}
添加途径点
// 途径点选中数据时
const handleInputConfirm = (index, val) => {
console.log(index, val)
let selected = searchOptions.value.find(item=>item.value == val);
routePoints.value[index].inputVisible = false;
routePoints.value[index].name = selected.label
// 设置点
let mapinfo = selected.mapinfo
let featureGroup = layerArray[index];
if (mapInstance && featureGroup && mapInstance.hasLayer(featureGroup)) {
mapInstance.removeLayer(featureGroup)
}
featureGroup = L.featureGroup().addTo(mapInstance);
if(featureGroup){
const icon = new L.Icon({
iconUrl: locationIcon,
iconAnchor: [12, 41],
})
L.marker(mapinfo, { icon :icon }).addTo(featureGroup).bindTooltip('途径点'+index, {
offset: L.point([0, -30]),
direction: "top",
permanent: true
}).openTooltip();
layerArray[index] = featureGroup;
};
}
页面代码
<div class="h-full flex">
<div class="flex-none flex flex-col mx-2 my-4 p-2 legend_message bg-white w-[400px]">
<div class="flex-none">
<div class="title">
路线配置
</div>
<div class="title_message">
起止点设置
</div>
<Form :label-col="{ style: { width: '70px', textAlign: 'left', margin: '0' } }" style="margin-top: 20px;">
<FormItem label="起始点:">
<Select
v-model:value="searchStartValue"
show-search
placeholder="请输入起始点"
:options="searchStartOptions"
:filter-option="filterStartOption"
@select="handleStartSelect"
@search="searchStartpoint"
></Select>
</FormItem>
<FormItem label="终点:">
<Select
v-model:value="searchEndValue"
show-search
placeholder="请输入终点"
:options="searchEndOptions"
:filter-option="filterEndOption"
@select="handleEndSelect"
@search="searchEndpoint"
></Select>
</FormItem>
</Form>
<Button type="primary" @click="choose">选点</Button>
<Button type="primary" @click="submit">提交</Button>
</div>
<div class="flex-none">
<div class="title_message">
路线规划
</div>
<Timeline style="margin-top: 20px;">
<TimelineItem v-for="(route, index) in routePoints" :key="index">
<Select
ref="inputRef"
v-if="route.inputVisible && index!=0 && index != routePoints.length-1"
v-model:value="route.name"
show-search
placeholder="请输入终点"
:options="searchOptions"
:filter-option="filterEndOption"
@select="handleInputConfirm(index, route.name)"
@search="searchPoint"
size="small"
:style="{ width: '250px' }"
></Select>
<a-tag v-else style="background: #fff;" @click="showInput(index)">
<plus-outlined />
{{route.name}}
</a-tag>
<div style="float: right;gap: 8px;" >
<!-- <FormOutlined style="margin-right: 10px;" @click=""/> -->
<PlusCircleOutlined @click="addRoutePoint(index)" v-if="index != routePoints.length-1"/>
<MinusCircleOutlined style="margin-left: 10px" @click="removeRoutePoint(index)" v-if="index != routePoints.length-1"/>
</div>
</TimelineItem>
</Timeline>
</div>
<div class="flex-none" style="text-align: right;">
<span >
<a-button type="primary" @click="preStep">
上一步
</a-button>
</span>
<span class="ml-2" >
<a-button type="primary" @click="nextStep">
下一步
</a-button>
</span>
</div>
</div>
<div class="legend_message ml-2 flex grow mx-2 my-4 ">
<MapView ref="mapRef" @after-init="handleMapInit"/>
</div>
</div>
本人也是前端菜鸡, 具体原因也不清楚, 有清楚的大佬还望告知一声, 希望能学习一下. 活到老, 学到老😊