3

I am trying to combine fabricJS with Google Maps. What I've done is to lay a canvas over the map div to display shapes over the map. The problem is that google map events are not trigger anymore. I searched the internet for solutions and found the css tag pointer-event should propagate the click events to the underlying layers, but that didn't work for me. I also tried to add a event with addDomListener, but no luck also. The click event would trigger, but the google.maps.event.trigger didn't.

I just started, so there is nothing fancy to see yet. I'm kind of new to web development, so I figured I ask here before wasting my time with something that is not possible.

This is my html file:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        #holder {
            height:700px;
            width: 700px;
            position:relative;

        }
        #canvasholder{
            height: 700px;
            width: 700px;
            position: absolute;
        }
        html, body {
            height: 100%;
            margin: 0;
            padding: 0;
        }
        #map-canvas {
            position: absolute;

            height: 700px;
            width: 700px;
            z-index: -1;
        }
        #canvas{
            position: absolute;
            height: 700px;
            widht: 700px;
            pointer-events: none;
            opacity: 1;
            z-index: 1;
        }
    </style>
</head>
<body>
<script src="https://rawgit.com/kangax/fabric.js/master/dist/fabric.js"></script>
<div id="holder">
    <div id="canvasholder">
        <canvas id="canvas"></canvas>
    </div>
    <div id="map-canvas"></div>
</div>

<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyAJ4aYR2NFbLLzh_tkya-rE40gCl-hPpLc&callback=initMap"
        async defer></script>
<script src="./app.js"></script>

</body>
</html>

And my Javascript file:

var map;
var canvas;
function initMap() {
    map = new google.maps.Map(document.getElementById('map-canvas'), {
        center: {lat: -34.397, lng: 150.644},
        zoom: 8
    });
    google.maps.event.addDomListener(document.getElementById("canvasholder").firstElementChild, "click", function(e){
        google.maps.event.trigger(map, "click", e);
    })
    canvas = new fabric.Canvas("canvas");
    canvas.setHeight(700);
    canvas.setWidth(700);
    canvas.setBackgroundColor('', canvas.renderAll.bind(canvas));
    canvas.add(new fabric.Circle({ radius: 30, fill: '#f55', top: 100, left: 100 }));
}
Essometer
  • 77
  • 10
  • related question: [How do I add a simple onClick event handler to a canvas element?](http://stackoverflow.com/questions/9880279/how-do-i-add-a-simple-onclick-event-handler-to-a-canvas-element) – geocodezip Oct 28 '16 at 17:04
  • You may have a typo, the correct syntax is: `pointer-events:none;` (note the plural "events"). – markE Oct 28 '16 at 20:10

1 Answers1

1

You can trigger a click on the map with the code below. You don't have any other Google Maps objects in your example (markers, polygons, polylines, etc), this won't work for those directly, you will have to determine if the click falls on one of them and trigger its click event for that to happen.

modified from the related question:

document.getElementById("canvasholder").addEventListener("click", getPosition, false);

function getPosition(event) {
  var x = event.x;
  var y = event.y;

  var canvas = document.getElementById("canvas");

  x -= canvas.offsetLeft;
  y -= canvas.offsetTop;

  console.log("x:" + x + " y:" + y);

  // propagate click to map
  var latLng = projection.fromContainerPixelToLatLng(new google.maps.Point(x, y));
  google.maps.event.trigger(map, 'click', {
    latLng: latLng
  });
}

proof of concept fiddle

code snippet:

var map;
var canvas;

function initMap() {
  map = new google.maps.Map(document.getElementById('map-canvas'), {
    center: {
      lat: -34.397,
      lng: 150.644
    },
    zoom: 8
  });

  MyOverlay.prototype = new google.maps.OverlayView();
  MyOverlay.prototype.onAdd = function() {}
  MyOverlay.prototype.onRemove = function() {}
  MyOverlay.prototype.draw = function() {}

  function MyOverlay(map) {
    this.setMap(map);
  }

  var overlay = new MyOverlay(map);
  var projection;

  // Wait for idle map
  google.maps.event.addListener(map, 'idle', function() {
    // Get projection
    projection = overlay.getProjection();
  })



  google.maps.event.addDomListener(document.getElementById("canvasholder").firstElementChild, "click", function(e) {
    console.log("click:" + e)
    google.maps.event.trigger(map, "click", e);
  });
  document.getElementById("canvasholder").addEventListener("click", getPosition, false);

  function getPosition(event) {
    var x = event.x;
    var y = event.y;

    var canvas = document.getElementById("canvas");

    x -= canvas.offsetLeft;
    y -= canvas.offsetTop;

    console.log("x:" + x + " y:" + y);

    // propagate click to map
    var latLng = projection.fromContainerPixelToLatLng(new google.maps.Point(x, y));
    google.maps.event.trigger(map, 'click', {
      latLng: latLng
    });
  }
  google.maps.event.addListener(map, "click", function(e) {
    console.log("click:" + e.latLng);
    var marker = new google.maps.Marker({
      position: e.latLng,
      map: map,
      title: e.latLng.toUrlValue(6),
      icon: {
        url: "https://maps.gstatic.com/intl/en_us/mapfiles/markers2/measle.png",
        size: new google.maps.Size(7, 7),
        anchor: new google.maps.Point(3.5, 3.5)
      }
    });
  });
  canvas = new fabric.Canvas("canvas");
  canvas.setHeight(700);
  canvas.setWidth(700);
  canvas.setBackgroundColor('', canvas.renderAll.bind(canvas));
  canvas.add(new fabric.Circle({
    radius: 30,
    fill: '#f55',
    top: 100,
    left: 100
  }));
}
google.maps.event.addDomListener(window, "load", initMap);
#holder {
  height: 700px;
  width: 700px;
  position: relative;
}
#canvasholder {
  height: 700px;
  width: 700px;
  position: absolute;
}
html,
body {
  height: 100%;
  margin: 0;
  padding: 0;
}
#map-canvas {
  position: absolute;
  height: 700px;
  width: 700px;
  z-index: -1;
}
#canvas {
  position: absolute;
  height: 700px;
  widht: 700px;
  pointer-events: none;
  opacity: 1;
  z-index: 1;
}
<script src="https://maps.googleapis.com/maps/api/js"></script>
<script src="https://cdn.rawgit.com/kangax/fabric.js/master/dist/fabric.js"></script>
<div id="holder">
  <div id="canvasholder">
    <canvas id="canvas"></canvas>
  </div>
  <div id="map-canvas"></div>
</div>
Community
  • 1
  • 1
geocodezip
  • 158,664
  • 13
  • 220
  • 245
  • Thank you for your help. So if I understand correctly, if I would for example like to have a drag map functionality, I need to implement the events for dragging on the canvas and then tell the map under it how to react. – Essometer Oct 29 '16 at 12:07