Created
January 21, 2016 16:31
-
-
Save unglud/7faf295e0b5efc09488f to your computer and use it in GitHub Desktop.
Google maps Module. Can add marker, directions and draw path by directions
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var ProjectMap = (function () { | |
"use strict"; | |
var _center = {lat: 50.159573, lng: 71.918242}, // map center on load | |
_points = [], | |
_map = null, | |
_useDirectios = false, // generate directions with google.maps.DirectionsService() or use simple google.maps.Polyline | |
_cache = [], // cache for google.maps.Geocoder() | |
_isDraggable = !('ontouchstart' in document.documentElement); | |
// constructor | |
var module = function (json, directions) { | |
if (directions != undefined) _useDirectios = directions; | |
addPoints(json); | |
renderMap(); | |
}; | |
var renderMap = function () { | |
var mapOptions = { | |
center: _center, | |
zoom: 7, | |
mapTypeControl: false, | |
draggable: _isDraggable, | |
scrollwheel: false, | |
streetViewControl: false, | |
styles: // [{"stylers":[{"visibility":"simplified"}]},{"stylers":[{"color":"#1f2b40"}]},{"featureType":"water","stylers":[{"color":"#131313"},{"lightness":7}]},{"elementType":"labels.text.fill","stylers":[{"visibility":"on"},{"lightness":25}]}] | |
[{ | |
"featureType": "all", | |
"elementType": "labels.text.fill", | |
"stylers": [{"color": "#3b537d"}] | |
}, { | |
"featureType": "all", | |
"elementType": "labels.text.stroke", | |
"stylers": [{"color": "#000000"}, {"lightness": 13}] | |
}, { | |
"featureType": "administrative", | |
"elementType": "geometry.fill", | |
"stylers": [{"color": "#000000"}] | |
}, { | |
"featureType": "administrative", | |
"elementType": "geometry.stroke", | |
"stylers": [{"color": "#144b53"}, {"lightness": 14}, {"weight": 1.4}] | |
}, { | |
"featureType": "landscape", | |
"elementType": "all", | |
"stylers": [{"color": "#1f2b40"}] | |
}, { | |
"featureType": "poi", | |
"elementType": "geometry", | |
"stylers": [{"color": "#0c4152"}, {"lightness": 5}] | |
}, { | |
"featureType": "road.highway", | |
"elementType": "geometry.fill", | |
"stylers": [{"color": "#000000"}] | |
}, { | |
"featureType": "road.highway", | |
"elementType": "geometry.stroke", | |
"stylers": [{"color": "#46546d"}, {"lightness": 25}] | |
}, { | |
"featureType": "road.arterial", | |
"elementType": "geometry.fill", | |
"stylers": [{"color": "#000000"}] | |
}, { | |
"featureType": "road.arterial", | |
"elementType": "geometry.stroke", | |
"stylers": [{"color": "#0b3d51"}, {"lightness": 16}] | |
}, { | |
"featureType": "road.local", | |
"elementType": "geometry", | |
"stylers": [{"color": "#000000"}] | |
}, /*{"featureType":"transit","elementType":"all","stylers":[{"color":"#146474"}]},*/{ | |
"featureType": "water", | |
"elementType": "all", | |
"stylers": [{"color": "#021019"}] | |
}] | |
}; | |
_map = new google.maps.Map(document.getElementById('map-view'), mapOptions); | |
// if only 1 point render it on map | |
if (_points.length == 1) { | |
addMarker() | |
} | |
// if several, render path | |
if (_points.length > 1) { | |
addPath() | |
} | |
}; | |
var addMarker = function () { | |
var point = getPoint(_points[0]); // return promise | |
point.done(function (p) { | |
var marker = new google.maps.Marker({ | |
position: p, | |
map: _map, | |
zIndex: 100, | |
icon: '/i/ico-mapmarker.png', | |
title: '' | |
}); | |
marker.setMap(_map); | |
_map.setCenter(p); | |
}).fail(function (message) { | |
console.error(message); | |
}); | |
}; | |
var addPath = function () { | |
// for first and last points generate markers | |
$.when(getPoint(_points[0]), getPoint(_points[_points.length - 1])) | |
.done(function (first, last) { | |
var startMarker = new google.maps.Marker({ | |
position: first, | |
map: _map, | |
zIndex: 100, | |
icon: '/i/start-point.png', | |
title: '' | |
}); | |
var endMarker = new google.maps.Marker({ | |
position: last, | |
map: _map, | |
zIndex: 100, | |
icon: '/i/end-point.png', | |
title: '' | |
}); | |
startMarker.setMap(_map); | |
endMarker.setMap(_map); | |
}).fail(function (message) { | |
console.error(message); | |
}); | |
// preprocess all points without deffered object | |
// in result we will get addresses as is, but coordinates will transform to LatLng | |
var flightPlanCoordinates = _points.map(function (el) { | |
return getPoint(el, true); | |
}); | |
var direction = getDirection(flightPlanCoordinates); // returns promise | |
var flightPath = new google.maps.Polyline({ | |
path: [], | |
geodesic: true, | |
zIndex: 90, | |
strokeColor: '#80d460', | |
strokeOpacity: 1.0, | |
strokeWeight: 4 | |
}); | |
direction.done(function (result) { | |
// if directions is used, we get all legs (lines, paths), generated by google and draw our own designed lines | |
if (_useDirectios) { | |
var legs = result.routes[0].legs; | |
for (var i = 0; i < legs.length; i++) { | |
var steps = legs[i].steps; | |
for (var j = 0; j < steps.length; j++) { | |
var nextSegment = steps[j].path; | |
for (var k = 0; k < nextSegment.length; k++) { | |
flightPath.getPath().push(nextSegment[k]); | |
} | |
} | |
} | |
} else { | |
// else use simple drawing with all initial points we have | |
// put all promises to array | |
// it will be arguments for $.when(defPoints[0],defPoints[1]...defPoints[n]) | |
var defPoints = _points.map(function (el) { | |
return getPoint(el); | |
}); | |
// "apply" for possibility pass many arguments to function as array | |
$.when.apply(null, defPoints) | |
.done(function () { // defer returns as many arguments as $.when() got | |
flightPath.setPath(arguments); | |
}).fail(function (message) { | |
console.error(message); | |
}); | |
} | |
// zooming map, that we see all path | |
var bounds = result.routes[0].bounds; | |
_map.fitBounds(bounds); | |
_map.setCenter(bounds.getCenter()); | |
flightPath.setMap(_map); | |
}).fail(function (message) { | |
console.error(message); | |
}); | |
}; | |
var addPoints = function (json) { | |
/* | |
* JSON look like this | |
* [ | |
* {"MIGX_id":"1","point":"Астана, Казахстан"}, | |
* {"MIGX_id":"2","point":"Ерейментау, Казахстан, Акмолинская область"}, | |
* {"MIGX_id":"3","point":"поселок Шидерты, Казахстан, Павлодарская область, городской акимат Екибастуз"} | |
* ] | |
* */ | |
if (json.length) | |
_points = JSON.parse(json).map(function (point) { | |
return point.point; | |
}); | |
// now it simple flat array | |
}; | |
var getPoint = function (point, nodef) { | |
var deferred = $.Deferred(); | |
var pointsParset = point.split(","); // try split string, if it has LatLng "51.6935438,74.5552978" | |
var points = { | |
lat: parseFloat(pointsParset[0]), | |
lng: parseFloat(pointsParset[1]) | |
}; | |
// if after parseFloat it is Float between -180 and 180 | |
// then return LatLng as promise | |
if ( | |
(!isNaN(points.lat) && points.lat <= 180 && points.lat >= -180) && | |
(!isNaN(points.lng) && points.lng <= 180 && points.lng >= -180) | |
) { | |
if (nodef) return points; | |
deferred.resolve(points); | |
return deferred.promise(); | |
} else { | |
// else if it address string, try resolve it with google.maps.Geocoder() | |
if (nodef) return point; | |
return getPointByAddress(point); // returns promise | |
} | |
}; | |
var getPointByAddress = function (address) { | |
var deferred = $.Deferred(); | |
// cache for geodata | |
if (address in _cache) { | |
deferred.resolve(_cache[address]); | |
return deferred.promise() | |
} | |
var geocoder = new google.maps.Geocoder(); | |
if (geocoder) { | |
geocoder.geocode({'address': address}, function (results, status) { | |
if (status == google.maps.GeocoderStatus.OK) { | |
if (status != google.maps.GeocoderStatus.ZERO_RESULTS) { | |
deferred.resolve(results[0].geometry.location); | |
_cache[address] = results[0].geometry.location; | |
} else { | |
deferred.reject("No results found"); | |
} | |
} else { | |
deferred.reject("Geocode was not successful for the following reason: " + status); | |
} | |
}); | |
} else { | |
deferred.reject('Geocoder don\'t exists') | |
} | |
return deferred.promise() | |
}; | |
var getDirection = function (ponts) { | |
var directionsService = new google.maps.DirectionsService(); | |
var deferred = $.Deferred(); | |
var request = { | |
origin: ponts[0], | |
destination: ponts[ponts.length - 1], | |
travelMode: google.maps.TravelMode.DRIVING, | |
}; | |
// if we have > 2 points, all points except first and last mast be in waypoints object | |
if (ponts.length > 2) { | |
var waypoints = ponts.slice(1, -1).map(function (p) { | |
return { | |
location: p, | |
stopover: false | |
}; | |
}); | |
request.waypoints = waypoints; | |
} | |
directionsService.route(request, function (result, status) { | |
if (status == google.maps.DirectionsStatus.OK) { | |
deferred.resolve(result); | |
} else { | |
deferred.reject("Directions Service was not successful for the following reason: " + status); | |
} | |
}); | |
return deferred.promise() | |
}; | |
// prototype | |
module.prototype = { | |
//addPoints: addPoints | |
}; | |
// return module | |
return module; | |
})(); | |
// usage | |
$(function(){ | |
new ProjectMap('[{"MIGX_id":"1","point":"Астана, Казахстан"},{"MIGX_id":"2","point":"Ерейментау, Казахстан, Акмолинская область"},{"MIGX_id":"3","point":"поселок Шидерты, Казахстан, Павлодарская область, городской акимат Екибастуз"}]'); | |
}) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment