使用自定义 Google 地图类型时画布上没有鼠标事件

问题描述 投票:0回答:1

我正在使用自定义地图类型为每个地图图块绘制画布。加载图块后,我会根据图块和图块内的像素位置在这些画布上进行绘制。我正在尝试添加一个 addEventListener 来检测相应图块上的鼠标移动。但是,我没有收到任何鼠标事件,因为 Google 地图图层正在处理这些事件。

要获取这些鼠标事件,我相信我必须使用自定义叠加层并通过 onAdd() 函数将canvas元素添加到overlayMouseTarget。

不幸的是,我不确定如何在我拥有的自定义地图类型中实现这一点。这是一个函数,说明了我当前正在使用的内容。在这种情况下,画布事件侦听器永远不会触发。

我将在哪里以及如何在此处实现每个图块自定义叠加层,以允许我捕获画布元素上的鼠标事件?

async function drawTest() {
    await google.maps.importLibrary("maps");

    var map = new google.maps.Map(document.getElementById("map"), {
      zoom: 7,
      minZoom: 3,
      center: {lat: 38, lng: -5}
    });

    function CoordMapType(tileSize) {
      this.tileSize = tileSize;
    }

    CoordMapType.prototype.getTile = function(tile, zoom, ownerDocument) {
      const canvas = ownerDocument.createElement('canvas');
      canvas.id = "canvas_" + tile.x + "," + tile.y;
      canvas.width = 256;
      canvas.height = 256;
      canvas.addEventListener("mousemove", (e) => {
        console.log(e);
      });

      // Adding the overlay code here results in mouse events.
      // But the canvases appended to the center of the map.

      return canvas;
    };
    
    map.overlayMapTypes.insertAt(0, new CoordMapType(new google.maps.Size(256, 256)));

    let positions = [
      {tileX: 61, tileY: 48, pX: 100, pY: 200},
      {tileX: 62, tileY: 49, pX: 231, pY: 180},
    ]

    google.maps.event.addListener(map, 'tilesloaded', function() {
      for (let i = 0; i < positions.length; i++) {
        let canvas = document.getElementById("canvas_" + positions[i].tileX + "," + positions[i].tileY);
        let ctx = canvas.getContext("2d");
        ctx.fillStyle = "red";
        ctx.fillRect(positions[i].pX, positions[i].pY, 10, 10);
      }
    });
}
drawTest();

到目前为止,我已经尝试对 getTile() 以及在tilesloaded 侦听器发生之后实现以下内容。这最终会将所有画布附加到中心的 div,这会偏移画布位置,从而导致画布绘图的位置不正确。

var CanvasOverlay = function() {};
CanvasOverlay.prototype = new google.maps.OverlayView();
CanvasOverlay.prototype.onAdd = function() {   
  console.log(tile)         
  let panes = this.getPanes();
  panes.overlayMouseTarget.appendChild(canvas);
};
var canvasOverlay = new CanvasOverlay();
canvasOverlay.setMap(map);

这里有一个 JSFiddle,它可以帮助可视化问题。

https://jsfiddle.net/stjx1dkm/16/

javascript google-maps dom-events
1个回答
0
投票

感谢阿布朗修斯教授的评论。这些帖子和一夜好眠让我得到了我所需要的。

以下是我如何使用自定义叠加层和自定义地图类型的组合来生成可以查看鼠标事件的每图块叠加层。值得注意的是 getTileBounds 函数,它定义了图块的西南角和东北角的纬度和经度。这些角用作覆盖层的边界。 API 文档中提供了帮助创建您自己的函数的文档,但我发现 Dr.Molle 的这个答案 更有帮助。

async function drawTest() {
    await google.maps.importLibrary("maps");

    class MyOverlay extends google.maps.OverlayView {
        bounds;
        div;
        canvas;
        constructor(bounds, canvas) {
          super();
          this.bounds = bounds;
          this.canvas = canvas;
        }
    
        onAdd() {
            this.div = document.createElement("div");
            this.div.id = "overlayMouseTarget";
            this.div.style.borderStyle = "none";
            this.div.style.borderWidth = "0px";
            this.div.style.position = "absolute";

            this.div.appendChild(this.canvas);
    
            const panes = this.getPanes();
            panes.overlayMouseTarget.appendChild(this.div);
        }
    
        draw() {
            const overlayProjection = this.getProjection();
            const sw = overlayProjection.fromLatLngToDivPixel(this.bounds.sw);
            const ne = overlayProjection.fromLatLngToDivPixel(this.bounds.ne);
    
            if (this.div) {
                this.div.style.left = sw.x + "px";
                this.div.style.top = ne.y + "px";
                this.div.style.width = ne.x - sw.x + "px";
                this.div.style.height = sw.y - ne.y + "px";
            }
        }
    }

    var map = new google.maps.Map(document.getElementById("map"), {
        zoom: 7,
        minZoom: 3,
        center: {lat: 38, lng: -5}
    });

    function CoordMapType(tileSize) {
        this.tileSize = tileSize;
    }

    CoordMapType.prototype.getTile = function(tile, zoom, ownerDocument) {

        const bounds = getTileBounds(tile, 256, zoom);

        const canvas = document.createElement('canvas');
        canvas.id = "canvas_" + tile.x + "," + tile.y;
        canvas.width = 256;
        canvas.height = 256;
        canvas.addEventListener("mousemove", (e) => {
            console.log(e);
        });

        var canvasOverlay = new MyOverlay(bounds, canvas);
        canvasOverlay.setMap(map);

        return canvas;
    };
    
    map.overlayMapTypes.insertAt(0, new CoordMapType(new google.maps.Size(256, 256)));

    let positions = [
        {tileX: 61, tileY: 48, pX:100, pY: 200},
        {tileX: 62, tileY: 49, pX:231, pY: 180},
    ]

    google.maps.event.addListener(map, 'tilesloaded', function() {
        for (let i = 0; i < positions.length; i++) {
            let canvas = document.getElementById("canvas_" + positions[i].tileX + "," + positions[i].tileY);
            let ctx = canvas.getContext("2d");
            ctx.fillStyle = "red";
            ctx.fillRect(positions[i].pX, positions[i].pY, 10, 10);
        }
    });
}
© www.soinside.com 2019 - 2024. All rights reserved.