Skip to content

Instantly share code, notes, and snippets.

@silesky
Last active September 13, 2022 01:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save silesky/05bd33566bbc7eb30be3b6b686336955 to your computer and use it in GitHub Desktop.
Save silesky/05bd33566bbc7eb30be3b6b686336955 to your computer and use it in GitHub Desktop.
React custom Google Maps component
import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import { iconYouAreHere, iconPin } from 'icons';
import styles from './styles.css';
const loadScript = src => {
const ref = global.document.getElementsByTagName('script')[0];
const script = global.document.createElement('script');
script.src = src;
script.async = false;
ref.parentNode.insertBefore(script, ref);
};
// default gps coordinates (for demo purposes).
class GoogleMap extends Component {
static defaultProps = {
selectedLocation: {
geolocation: [],
title: '',
},
zoom: 16,
mapCenterCoords: [27.70818068675375, -97.3250101343628],
youAreHereCoords: [27.716433466839, -97.328835725784],
gmApiKey: 'xxx',
};
static removeAllMarkers() {
global.mapMarkers.forEach(eachMarker => eachMarker.setMap(null));
global.mapMarkers = [];
}
static createMarkerIcon(url) {
const { Point } = global.google.maps;
return {
url, // many more options exist in the google maps api docs.
origin: new Point(0, 0),
anchor: new Point(35, 90),
};
}
static changeMarkerPosition(coords = [], title = '') {
const { Marker, LatLng, Animation } = global.google.maps;
GoogleMap.removeAllMarkers();
const marker = new Marker({
position: new LatLng(...coords),
icon: GoogleMap.createMarkerIcon(iconPin),
title,
animation: Animation.DROP, // bounce is also cool
optimized: false, // make markers higher up go on bottom (enables proper ZIndex behavior)
});
global.mapMarkers = [marker];
marker.setMap(global.MapInstance); // display current marker
}
static setCenter([lat, lng], animated = true) {
const offset = 0.008; // increase to move the center up.
const latWithOffset = lat - offset;
global.MapInstance.setOptions({ zoom: 16 });
if (!animated) {
global.MapInstance.setCenter({ lat: latWithOffset, lng });
} else {
global.MapInstance.panTo({ lat: latWithOffset, lng });
}
componentDidMount() {
global.mapLoadedCallback = this.mapLoadedCallback; // assign instance method to glonal so it can be called by loaded script
const { gmApiKey } = this.props;
const apiUrl = `http://maps.googleapis.com/maps/api/js?&callback=mapLoadedCallback&key=${gmApiKey}`;
if (!global.google || !global.google.maps) {
// don't load twice
loadScript(apiUrl); // load script and trigger callback
} else {
this.mapLoadedCallback(); // manually trigger callback
}
global.mapMarkers = [];
}
componentWillReceiveProps({ selectedLocation: { geolocation, title } }) {
const userSelectedNewLocation = title !== this.props.selectedLocation.title;
if (userSelectedNewLocation) {
GoogleMap.setCenter(geolocation);
GoogleMap.changeMarkerPosition(geolocation, title);
}
}
setYouAreHere = () => {
const { Marker, LatLng } = global.google.maps;
const marker = new Marker({
position: new LatLng(...this.props.youAreHereCoords),
icon: GoogleMap.createMarkerIcon(iconYouAreHere),
title: 'You are Here',
optimized: false,
});
marker.setMap(global.MapInstance);
}
getMapOptions = () => {
const { LatLng } = global.google.maps;
return {
zoom: this.props.zoom,
minZoom: 4,
center: new LatLng(...this.props.mapCenterCoords),
mapTypeControl: false, // Map / satellite button
streetViewControl: false, // little person button
zoomControl: false, // zoom button
fullscreenControl: false, // remove [__] button
clickableIcons: false,
};
}
mapLoadedCallback = () => {
const { Map } = global.google.maps;
global.MapInstance = new Map(
ReactDOM.findDOMNode(this),
this.getMapOptions(),
);
this.setYouAreHere(iconYouAreHere);
}
render() {
return <div className="maps__google_maps" />;
}
}
const Map = props =>
(<div className={styles.mapContainer}>
<GoogleMap {...props} />
</div>);
export default Map;
<Map
 youAreHereCoords={youAreHereCoords /* map origin (coordinates) */}
 selectedLocation={selectedLocation /* location to drop a pin (coordinates) */} 
/>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment