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

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属性已正确添加。

问题原因

  1. 事件绑定重复且处理逻辑错误:每次点击按钮都会绑定新的draw.create事件,导致多次触发;同时使用draw.add重复添加特征,而非修改Draw已创建的特征属性,样式无法感知到属性变化。
  2. 缺少绘制过程中的样式配置:绘制预览阶段的临时多边形未配置对应颜色,且样式未关联当前绘制类型。

解决方案

步骤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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 16:23:13