Mapbox-gl-draw自定义按钮绘制不同颜色多边形问题
解决Mapbox-gl-draw自定义类型多边形颜色不生效问题
问题场景
通过自定义按钮调用Mapbox-gl-draw的「绘制多边形」功能,希望给不同类型的多边形设置对应颜色:
- custom-button-1:绘制「operation-area」类型的绿色多边形
- custom-button-2:绘制「lifecycle-tree-area」类型的蓝色多边形
目前点击按钮能触发绘制,但最终多边形始终显示默认红色,尽管通过console.log确认user_draw_type属性已正确添加。
问题原因
- 事件绑定重复且处理逻辑错误:每次点击按钮都会绑定新的
draw.create事件,导致多次触发;同时使用draw.add重复添加特征,而非修改Draw已创建的特征属性,样式无法感知到属性变化。 - 缺少绘制过程中的样式配置:绘制预览阶段的临时多边形未配置对应颜色,且样式未关联当前绘制类型。
解决方案
步骤1:完善Draw初始化配置,添加绘制阶段样式
修改Draw的样式数组,补充已完成多边形和绘制中临时多边形的填充、边框样式,通过全局变量关联当前绘制类型:
import MapboxDraw from '@mapbox/mapbox-gl-draw'; // 存储当前要绘制的多边形类型,用于预览样式判断 let currentDrawType = null; export function initializeDrawTools(map) { const draw = new MapboxDraw({ displayControlsDefault: false, userProperties: true, controls: { line_string: true, trash: true, polygon: true, point: true, }, styles: [ // 已完成多边形填充样式 { id: 'gl-draw-polygon-fill', type: 'fill', filter: ['all', ['==', '$type', 'Polygon'], ['!=', 'mode', 'static']], paint: { 'fill-color': [ 'case', ['==', ['get', 'user_draw_type'], 'operation-area'], '#00ff00', ['==', ['get', 'user_draw_type'], 'lifecycle-tree-area'], '#0000ff', '#ff0000', // 默认红色 ], 'fill-opacity': 0.3, }, }, // 绘制中多边形填充样式(预览) { id: 'gl-draw-polygon-fill-active', type: 'fill', filter: ['all', ['==', '$type', 'Polygon'], ['==', 'mode', 'draw_polygon']], paint: { 'fill-color': [ 'case', ['==', currentDrawType, 'operation-area'], '#00ff00', ['==', currentDrawType, 'lifecycle-tree-area'], '#0000ff', '#ff0000', ], 'fill-opacity': 0.3, }, }, // 已完成多边形边框样式 { id: 'gl-draw-polygon-stroke', type: 'line', filter: ['all', ['==', '$type', 'Polygon'], ['!=', 'mode', 'static']], layout: { 'line-cap': 'round', 'line-join': 'round', }, paint: { 'line-color': [ 'case', ['==', ['get', 'user_draw_type'], 'operation-area'], '#006600', ['==', ['get', 'user_draw_type'], 'lifecycle-tree-area'], '#000066', '#cc0000', ], 'line-width': 2, }, }, // 绘制中多边形边框样式(预览) { id: 'gl-draw-polygon-stroke-active', type: 'line', filter: ['all', ['==', '$type', 'Polygon'], ['==', 'mode', 'draw_polygon']], layout: { 'line-cap': 'round', 'line-join': 'round', }, paint: { 'line-color': [ 'case', ['==', currentDrawType, 'operation-area'], '#006600', ['==', currentDrawType, 'lifecycle-tree-area'], '#000066', '#cc0000', ], 'line-width': 2, }, }, ] }); map.addControl(draw); return draw; }
步骤2:修改自定义按钮的绘制触发逻辑
修正事件绑定方式,使用map.once避免重复触发,直接通过draw.setFeatureProperty更新Draw内部的特征属性:
export function activateDrawMode(map, draw, category, type) { if (category !== 'polygon') return; // 更新当前绘制类型,用于预览样式判断 currentDrawType = type; // 移除之前的draw.create监听,防止重复触发 map.off('draw.create'); // 切换到多边形绘制模式 draw.changeMode('draw_polygon'); // 监听一次绘制完成事件,更新特征属性 map.once('draw.create', (e) => { const targetFeatureId = e.features[0].id; draw.setFeatureProperty(targetFeatureId, 'user_draw_type', type); }); }
原理说明
- 使用
draw.setFeatureProperty直接修改Draw内部存储的特征属性,能立即触发样式重新计算,解决属性设置后样式不更新的问题。 - 添加绘制阶段的样式配置,通过
currentDrawType变量让预览中的多边形也显示对应颜色,提升用户体验。 - 用
map.once替代map.on,确保每次绘制完成仅触发一次属性更新,避免重复绑定事件导致的逻辑混乱。
内容的提问来源于stack exchange,提问作者Truls
相关产品推荐
相关产品推荐

