从地图点击事件中获取 LngLat 并将其绘制到 mapboxGL 的 canvas 图层上

Taking LngLat from Map click event and drawing it onto a canvas layer for mapboxGL

我正在使用 mapboxGL,但我无法弄清楚...有没有人幸运地从点击事件中获取 lng/lat,然后将其绘制在单独的 canvas 图层上.

示例如下:

map.on('click', (e) => {
  const canvas = document.createElement('canvas');
  const ctx = canvas.getContext('2d');

  ctx.beginPath();
  ctx.arc(e.lngLat.lat, e.lngLat.lng, 10, 0, 2 * Math.PI, false);
  ctx.fillStyle = 'green';
  ctx.fill();

  map.addLayer({
    id: 'canvas-layer',
    type: 'raster',
    source: {
      type: 'canvas',
      canvas: canvas,
      coordinates: [
        map.getBounds().getNorthWest().toArray(),
        map.getBounds().getNorthEast().toArray(),
        map.getBounds().getSouthEast().toArray(),
        map.getBounds().getSouthWest().toArray(),
      ],
    },
  });
});

canvas 源的坐标似乎是正确的,但实际圆的 lng/lat 有很大偏差,我不知道是否应该使用 x/y 坐标或使用 map.project() 或其他东西...

代码太少,我无法理解创建 canvas 和图层的 objective,每次单击地图中的一个点只是为了创建一个圆圈。首先,Mapbox 第二次会报错,因为你总是为图层使用相同的名称。我要做的是在 HTML 中静态创建 canvas 就在地图

上方
<canvas id="canvasID" width="682" height="400" style="overflow:hidden">Canvas not supported</canvas>
<div id="map"></div>

然后创建地图并将 canvas 调整为地图的大小。

var map = new mapboxgl.Map({
    container: 'map',
    zoom: mapConfig.NYC.zoom,
    minZoom: mapConfig.NYC.zoom,
    center: mapConfig.NYC.center,
    style: 'mapbox://styles/mapbox/streets-v11'
});

map.setMaxBounds([map.getBounds().getSouthWest().toArray(), map.getBounds().getNorthEast().toArray()]);

let width = map.getCanvas().clientWidth;
let height = map.getCanvas().clientHeight;
canvas.width = width;
canvas.height = height;

然后是点击事件前的层和源。

map.on('load', function () {
    map.addSource('canvas-source', {
        type: 'canvas',
        canvas: 'canvasID',
        coordinates: [
            map.getBounds().getNorthWest().toArray(),
            map.getBounds().getNorthEast().toArray(),
            map.getBounds().getSouthEast().toArray(),
            map.getBounds().getSouthWest().toArray(),
        ],
        animate: true
    });

    map.addLayer({
        id: 'canvas-layer',
        type: 'raster',
        source: 'canvas-source'
    });
...
});

然后我会在加载时在地图中添加事件,只是为了绘制一个圆圈,而不是使用 e.lngLat,基本上使用鼠标指针参数,因为现在 canvas大小和坐标等于 mapbox 初始大小和缩放视图。

map.on('click', (e) => {
    color = "#ff0000";
    ctx.beginPath();
    ctx.arc(e.point.x, e.point.y, radius, 0, Math.PI * 2, false);
    ctx.strokeStyle = "#ff0000";
    ctx.stroke();
});

我创建了一个 fiddle 解决方案 how to add a custom canvas and draw circles on click

结果是这样的,每次点击都会在canvas层渲染一个新的圆圈。

注意:使用这种方法会有一些局限性,例如限制地图的边界和平移,当然在缩放时您需要重新计算所查看边界内的鼠标单击位置。