Skip to content

Instantly share code, notes, and snippets.

@Sphinxxxx
Last active April 20, 2024 13:57
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Sphinxxxx/23f991f84ab77b05658cab8468fe7112 to your computer and use it in GitHub Desktop.
Save Sphinxxxx/23f991f84ab77b05658cab8468fe7112 to your computer and use it in GitHub Desktop.
Google Maps interactive SVG overlay
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyDFakIzRcdWcvBjFvdBnREF--j-7AC3YF8"></script>
<div id="map"></div>
<!-- This is the SVG element we'll place on top of the map -->
<svg id="svg1" xmlns="http://www.w3.org/2000/svg" width="400" height="400" viewBox="0 0 32 32">
<g>
<circle cx="7.5" cy="7" r=".8"/>
<path fill="green" d="M21.8 4.2c-4-1-7.2-.7-11.4 1.8C10.4 5 8 2.3 5 4.3 1.8 3.9 1.8 7 1.8 7S0 10.1 0 11.3c0 .8.4 1 .9 1.1 2.3-1.3 4.3-1 6-.7 1 .1 1.7.2 2.2 0a.4.4 0 0 1 .2.8c-.7.2-1.5 0-2.5 0a8.2 8.2 0 0 0-5.3.5c1.9 3.2 7 4.3 10.9 1.7l3 .3c.2 0 0 .7-.2 1.4 0 .2-2.8.8-2.9 1 0 .4 2.5 0 2.7.3.2.3-.3 1.5 0 2.1.1.4 1.4 0 1.8-.9.2-.4-.6-1.4-.4-1.7l1-2H19l3.1-.3c.2 0 .4.4.6.9.1.2-1.8.6-1.7.8.2.5 1.9.2 2.5.7.6.6.6 2.2 1.1 2.4.3 0 1.3-.7 1.1-1.7-.3-1.4-2-3.2-2-3.2a6 6 0 0 1 3 .3c2.5 1.3.6 11-5.7 11.5-3.4.3-4.6-2.4-4.2-4 .5-1.5 2.4-2.3 3.7-2.1 1.3.2 1.5 1.4 1 2.2l-.3.3a1.2 1.2 0 0 0-2.1.9 1.2 1.2 0 0 0 2.4.2 2 2 0 0 0 1-.6c1-1.1.9-3.2-1.3-4-2.3-.8-5.7.7-5.8 3.3 0 2.5 2.3 5.5 6.3 5.2 5.9-.3 10.2-6.5 10-12.2a12 12 0 0 0-9.9-11.6zM6.8 9.7a2.4 2.4 0 1 1 .1 0z"/>
<path fill="tomato" d="M15,25 q2.6,7.5 -8.0,5.0 c-8.0,-2.5 -5.3,-12.5 -2.6,-12.5"/>
</g>
</svg>
(function() {
"use strict";
//console.clear();
/**
Our custom overlay class, based on this example:
http://serversideguy.com/2017/10/31/how-do-i-place-svgs-on-a-google-map-using-custom-overlays/
More info:
https://developers.google.com/maps/documentation/javascript/customoverlays
*/
class SVGOverlay extends google.maps.OverlayView {
constructor(bounds, svg, map) {
super();
this.bounds = bounds;
this.svg = svg;
super.setMap(map);
}
/**
Will be called when the map is ready for the overlay to be attached.
*/
onAdd() {
const svg = this.svg;
svg.style.position = 'absolute';
//Add the SVG element to a map pane/layer that is able to receive mouse events:
const panes = super.getPanes();
panes.overlayMouseTarget.appendChild(svg);
}
/**
Whenever we need to (re)draw the overlay on the map, including when first added.
*/
draw() {
//Here, we need to find the correct on-screen position for our image.
//To achieve that, we simply ask the map's projection to calculate viewport pixels from the image's lat/lng bounds:
const projection = super.getProjection(),
bounds = this.bounds,
sw = projection.fromLatLngToDivPixel(bounds.getSouthWest()),
ne = projection.fromLatLngToDivPixel(bounds.getNorthEast());
//Place/resize the SVG element:
const s = this.svg.style;
s.left = sw.x + 'px';
s.top = ne.y + 'px';
s.width = (ne.x - sw.x) + 'px';
s.height = (sw.y - ne.y) + 'px';
}
} //SVGOverlay
function addEvent(target, type, handler) {
const targets = (typeof target === 'string') ? Array.from(document.querySelectorAll(target))
: [target];
targets.forEach(t => google.maps.event.addDomListener(t, type, handler));
}
function initMap() {
const map = new google.maps.Map(document.getElementById('map')),
mySVG = document.querySelector('#svg1');
//Say which area we want the image to occupy:
const svgBounds = new google.maps.LatLngBounds(
new google.maps.LatLng(62.281819, -150.287132),
new google.maps.LatLng(62.400471, -150.005608),
);
new SVGOverlay(svgBounds, mySVG, map);
//For convenience, zoom in on that area:
map.setCenter(svgBounds.getCenter());
map.fitBounds(svgBounds);
//Handle normal DOM events on the SVG element(s):
addEvent('path', 'click', e => {
console.log('Clicked!');
e.currentTarget.style.fill = '#' + Math.floor(Math.random() * 0xfffff);
});
addEvent('path', 'dblclick', e => {
//Avoid zooming here:
e.stopPropagation();
});
}
addEvent(window, 'load', initMap);
})();
body {
margin: 0;
height: 100vh;
}
#map {
height: 100%;
}
svg {
//For multiple SVGs on top of each other. See crtlf's edit here:
//https://stackoverflow.com/questions/50327032/google-maps-overlayview-make-only-svg-clickable
pointer-events: none;
path {
pointer-events: auto;
}
path {
cursor: pointer;
opacity: .7;
&:hover {
opacity: 1;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment