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

Laravel中Mapbox GL Draw多边形加载后无法正常显示问题

解决Laravel+Mapbox GL JS编辑页面多边形不显示问题

问题诊断

  1. 数据库存储的坐标存在多层JSON转义(重复引号包裹),导致读取后格式不符合GeoJSON要求
  2. 控制器对已被模型自动转换为数组的字段重复执行json_encode,加剧格式混乱
  3. 地图初始化时未等待Mapbox地图加载完成就尝试添加多边形
  4. 表单缺少存储多边形坐标的隐藏字段,导致保存和回显逻辑不完整

分步解决方案

1. 修复数据库坐标格式问题

模型已配置polygon_coordinates为array类型,保存时直接传入数组即可,禁止手动JSON编码。针对已存在的脏数据,可在模型中添加访问器自动处理多层转义:

// app/Models/ZoneCoverage.php
public function getPolygonCoordinatesAttribute($value)
{
    // 循环解码直到得到数组格式
    while (is_string($value)) {
        $decoded = json_decode($value, true);
        if (json_last_error() === JSON_ERROR_NONE) {
            $value = $decoded;
        } else {
            break;
        }
    }
    return $value;
}

2. 简化控制器逻辑

模型会自动将polygon_coordinates字段转为数组,无需手动json_encode,直接传递给视图即可:

// 控制器edit方法
public function edit($id)
{
    $zoneCoverage = ZoneCoverage::findOrFail($id);
    $salesRegions = SalesRegion::all();
    // 直接传递数组,避免重复编码
    $polygonCoordinates = $zoneCoverage->polygon_coordinates;

    return view('plugins/demo::zone_coverage.form', compact('zoneCoverage', 'salesRegions', 'polygonCoordinates'));
}

3. 修正视图地图加载逻辑

确保地图加载完成后再添加多边形,同时补充表单隐藏字段:

<!-- 在表单内部添加隐藏字段,用于存储多边形坐标 -->
<input type="hidden" name="polygon_coordinates" id="polygon_coordinates" value="{{ old('polygon_coordinates', json_encode($zoneCoverage->polygon_coordinates ?? [])) }}">

<!-- 修改initMap函数中的多边形加载部分 -->
function initMap() {
    mapboxgl.accessToken = 'pk.eyJ1Ijoia290aTQyIiwiYSI6ImNsdnVudDFyOTE2N3Myam53eTZpcGxkOG8ifQ.IuuMRUS4czPqGuYWnpJ6Ww';
    const map = new mapboxgl.Map({
        container: 'map',
        style: 'mapbox://styles/mapbox/satellite-v9',
        center: [28.9784, 41.0082],
        zoom: 13
    });

    const draw = new MapboxDraw({
        displayControlsDefault: false,
        controls: {
            polygon: true,
            trash: true
        },
        defaultMode: 'draw_polygon'
    });
    map.addControl(draw);

    map.on('draw.create', updateArea);
    map.on('draw.delete', updateArea);
    map.on('draw.update', updateArea);

    function updateArea(e) {
        const data = draw.getAll();
        const answer = document.getElementById('calculated-area');
        if (data.features.length > 0) {
            const area = turf.area(data);
            const rounded_area = Math.round(area * 100) / 100;
            // 避免元素不存在导致报错
            if(answer) answer.innerHTML = `<p><strong>${rounded_area}</strong></p><p>square meters</p>`;
            document.getElementById('polygon_coordinates').value = JSON.stringify(data.features[0].geometry.coordinates);
        } else {
            if(answer) answer.innerHTML = '';
            if (e.type !== 'draw.delete')
                alert('Click the map to draw a polygon.');
        }
    }

    @if(isset($polygonCoordinates) && !empty($polygonCoordinates))
    // 等待地图load事件触发后再添加多边形
    map.on('load', function() {
        const polygon = {
            "type": "Feature",
            "geometry": {
                "type": "Polygon",
                "coordinates": {!! json_encode($polygonCoordinates) !!}
            }
        };
        draw.add(polygon);
        map.fitBounds(turf.bbox(polygon), { padding: 20 });
    });
    @endif

    setTimeout(function() {
        map.resize();
    }, 500);
}

4. 清理冗余依赖

视图中引入了Leaflet相关CSS,但实际使用的是Mapbox GL JS,可移除冗余代码:

<!-- 移除以下两行无用代码 -->
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.7.1/dist/leaflet.css" />
<link rel="stylesheet" href="https://unpkg.com/leaflet-draw@1.0.4/dist/leaflet.draw.css" />

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 01:52:11