You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Leaflet Draw重复触发draw:created事件导致绘图对象重复提交问题求助

解决Leaflet Draw重复触发draw:created事件导致数据重复提交的问题

我来帮你分析下这个问题,核心原因是事件监听器被重复绑定了,咱们一步步拆解解决:

问题根源

每次你执行new this.$leaflet.Draw.Marker(this.map.object)并启用后,又给地图对象绑定了一次draw:created事件。第二次创建标记/多边形时,地图上已经累积了多个相同的事件监听器,所以每次完成绘制都会触发所有监听器,导致打印多个事件对象、重复提交数据。

另外你遇到的两个错误也能对应上:

  • 调用removeHooks()报错:这是Leaflet Draw内部的私有钩子方法,不是给外部调用的,直接调用会因为内部_tooltip已被销毁而抛出空指针错误;
  • map.removeControl(draw)报错:因为你创建的是L.Draw.Marker绘制实例,而非L.Control.Draw控件,removeControl只对地图控件生效,所以无法识别这个Draw实例。

解决方案

方案1:只绑定一次draw:created事件(推荐)

把事件监听逻辑放到地图初始化阶段,而不是每次创建Draw实例时重复绑定。这样不管创建多少次绘制工具,事件只会触发一次:

// 在地图初始化的代码中,只绑定一次draw:created事件
this.map.object.on('draw:created', (event) => {
  event.layer.addTo(this.map.object)
  this.doCreateAnnotation(event)
})

// 创建标记点的函数只负责实例化并启用绘制工具
createMarker() {
  const draw = new this.$leaflet.Draw.Marker(this.map.object)
  draw.enable()
}

// 创建多边形的函数同理
createPolygon() {
  const draw = new this.$leaflet.Draw.Polygon(this.map.object)
  draw.enable()
}

方案2:每次绑定前移除旧的监听器

如果业务逻辑需要动态绑定/解绑,可以把事件处理函数抽成命名函数,每次创建Draw实例前先移除旧的监听器:

// 抽成命名函数,方便后续移除监听
handleDrawCreated = (event) => {
  event.layer.addTo(this.map.object)
  this.doCreateAnnotation(event)
}

createMarker() {
  // 先移除之前的draw:created监听器
  this.map.object.off('draw:created', this.handleDrawCreated)
  // 绑定新的监听器
  this.map.object.on('draw:created', this.handleDrawCreated)
  
  const draw = new this.$leaflet.Draw.Marker(this.map.object)
  draw.enable()
}

额外优化:绘制完成后禁用工具

如果需要在绘制完成后自动关闭当前绘制工具,可以在事件处理函数里添加禁用逻辑:

this.map.object.on('draw:created', (event) => {
  event.layer.addTo(this.map.object)
  this.doCreateAnnotation(event)
  // 禁用当前绘制工具
  this.$leaflet.Draw._getInstance(this.map.object).disable()
})

内容的提问来源于stack exchange,提问作者adamlmiller

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.30 08:53:11