Skip to content

Instantly share code, notes, and snippets.

@Sphinxxxx
Created June 12, 2019 16:47
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Sphinxxxx/31d33fbbaf3a48e767bab0360bbd52e5 to your computer and use it in GitHub Desktop.
Save Sphinxxxx/31d33fbbaf3a48e767bab0360bbd52e5 to your computer and use it in GitHub Desktop.
Stolpejakten 2018
<main>
<div id="map-canvas"></div>
<!--div id="summary" class="info-pane" ></div-->
</main>
(function() {
"use strict";
console.clear();
const _state = {
map: null,
markers: {
collection: null,
bounds: null,
},
curr_info: null, // current marker dialog open
curr_info_pane: null,
};
/**
* Add a marker to the Google Map
* @param {[type]} lat Latitude of marker
* @param {[type]} lon Longitude of marker
* @param {[type]} name Marker name
*/
function addMarker(lat, lon, name) {
const pos = new google.maps.LatLng(lat, lon),
marker = new google.maps.Marker({
//map: map,
position: pos,
//https://developers.google.com/maps/documentation/javascript/examples/icon-complex
icon: {
url: "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' width='30' height='30' viewBox='0,0 170,170'%3E %3Cdefs%3E %3Cpath id='map-outline' d='M10,40 l 50,-30 50,30 50,-30 v120 l-50,30 -50,-30 -50,30z' /%3E %3CclipPath id='map-clip'%3E %3Cuse xlink:href='%23map-outline' /%3E %3C/clipPath%3E %3C/defs%3E %3Cg clip-path='url(%23map-clip)'%3E %3Crect width='200' height='200' fill='lime' /%3E %3Crect x='60' width='50' height='200' fill='white' /%3E %3C/g%3E %3Cuse xlink:href='%23map-outline' stroke-width='6' fill='none' stroke='black'/%3E %3C/svg%3E",
anchor: new google.maps.Point(15, 15),
},
}),
info = {
name: name,
lat: lat,
lon: lon,
};
//http://stackoverflow.com/questions/11378450/google-map-api-v3-how-to-add-custom-data-to-markers
marker.__markerInfo = info;
const m = _state.markers;
m.bounds.extend(pos);
m.collection.addMarker(marker);
google.maps.event.addListener(marker, 'click', function () {
showInfo([marker], marker);
});
}
function pan_to(lat, lon) {
const map = _state.map,
pos = new google.maps.LatLng(lat, lon);
//var currZoom = map.getZoom();
let zoom = 15; //Math.max(currZoom+2, 14);
//http://stackoverflow.com/questions/5054515/zoom-in-to-marker-google-maps
map.setZoom(zoom);
map.panTo(pos);
}
function showInfo(markers, target) {
const s = _state;
const html = createInfoContent(markers);
if(s.curr_info_pane) {
s.curr_info_pane.innerHTML = html;
}
else {
if(s.curr_info) { s.curr_info.close(); }
s.curr_info = new google.maps.InfoWindow({
content: html,
});
s.curr_info.open(s.map, target);
}
}
function createInfoContent(markers) {
var htmls = markers.map(marker => {
const info = marker.__markerInfo,
html = `
<div class="info-window">
<a class="jump" href="#" data-lat="${info.lat}" data-lon="${info.lon}">
${info.name}
</a>
<!--div class="coords">
Lat: ${info.lat.toFixed(5)}<br/>
Lon: ${info.lon.toFixed(5)}<br/>
</div-->
</div>`;
return html;
});
var html = htmls.join('');
return html;
}
/**
* Initialize the Google Map
*/
function initialize() {
const s = _state,
m = s.markers;
s.curr_info_pane = document.querySelector('.info-pane');
const map = s.map = new google.maps.Map(
document.querySelector('#map-canvas'),
{
zoom: 3,
center: new google.maps.LatLng(61, 11),
mapTypeId: google.maps.MapTypeId.ROADMAP,
scaleControl: true,
//https://stackoverflow.com/questions/45729047/disable-the-ctrl-scroll-to-zoom-google-maps
gestureHandling: 'greedy',
}
);
google.maps.event.addListener(map, 'zoom_changed', function () {
if(s.curr_info) { s.curr_info.close(); }
});
//https://developers.google.com/maps/articles/toomanymarkers#viewportmarkermanagement
//https://googlemaps.github.io/js-marker-clusterer/docs/examples.html
m.collection = new MarkerClusterer(map, [], { gridSize: 30, zoomOnClick: false });
//http://stackoverflow.com/questions/13213849/force-an-information-window-instead-of-zoom-on-click-and-change-the-icon
//http://stackoverflow.com/questions/5710568/markerclusterer-on-click-zoom
google.maps.event.addListener(m.collection, 'clusterclick', function(cluster) {
var markers = cluster.getMarkers();
//Convert lat/long from cluster object to a usable MVCObject
//http://stackoverflow.com/questions/10520940/create-infowindow-for-clustered-markers-using-google-maps-v3
//http://jsfiddle.net/ErYub/
var target = new google.maps.MVCObject();
target.set('position', cluster.getCenter());
showInfo(markers, target);
});
m.bounds = new google.maps.LatLngBounds();
document.body.addEventListener('click', e => {
const jump = e.target.closest('a.jump');
if(jump) {
pan_to(jump.dataset.lat, jump.dataset.lon);
}
})
}
function load() {
function addMarkers(organizers) {
organizers.results.forEach(o => {
o.areas.forEach(a => {
const place = [
o.fylke.name,
o.kommuner.map(k => k.name).join('/') || o.alias,
a.name,
].join(' > ');
addMarker(a.location[1], a.location[0], place)
});
});
const s = _state;
s.map.fitBounds(s.markers.bounds);
}
const organizers = localStorage.sj2018_org;
if(organizers) {
console.log('Found cached organizers');
addMarkers(JSON.parse(organizers));
}
else {
fetch('https://api.stolpejakten.no/v6/organizers')
.then(r => {
console.log('fetched', r.status, r.statusText)
return r.text();
})
.then(t => {
localStorage.sj2018_org = t;
addMarkers(JSON.parse(t));
});
}
}
google.maps.event.addDomListener(window, 'load', () => {
initialize();
load();
});
})();
<script src="https://maps.googleapis.com/maps/api/js?v=3&key=AIzaSyDFakIzRcdWcvBjFvdBnREF--j-7AC3YF8"></script>
<script src="https://unpkg.com/gmaps-marker-clusterer@1"></script>
@import url(https://fonts.googleapis.com/css?family=Open+Sans:400,400italic,700);
/* Page layout */
body {
display: flex;
flex-flow: column nowrap;
height: 100vh;
margin: 0;
header {
}
main {
flex: 1 1 auto;
display: flex;
#map-canvas {
flex: 1 1 auto;
position: relative;
}
#summary {
}
}
}
/* Details */
body {
font-family: 'Open Sans', 'Helvetica Neue', Helvetica, Arial, sans-serif;
color: #444;
h2 {
margin: .5em;
}
}
#summary {
background: black;
color: white;
box-sizing: border-box;
padding: .5em 1em;
overflow: auto;
max-width: 50vw;
//transition: width .3s;
a {
color: orange;
}
}
.info-window {
+ .info-window {
margin-top: 1em;
}
.image {
display: inline-block;
position: relative;
vertical-align: top;
margin-right: 10px;
}
.img-thumb {
max-width: 120px;
max-height: 120px;
}
.coords {
display: inline-block;
margin-left: 1em;
}
.jump {
display: block;
cursor: pointer;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment