/**
* Jan Pecha
* http://pecha.it/
*/
var SRouteMap = (function () {
/**
* Mapa
* @param {Object} options
*/
function SRouteMap(options) {
var that = this;
var options = options;
var M = {};
/**
* Příprava mapy
*/
(function () {
if (options.center == undefined) { options.center = { lng: 14.395432, lat: 50.100604 }; }
if (options.zoom == undefined) { options.zoom = 9; }
M.Center = SMap.Coords.fromWGS84(options.center.lng, options.center.lat);
M.Map = new SMap(document.getElementById(options.elementId), M.Center, options.zoom);
M.Map.addDefaultLayer(SMap.DEF_BASE).enable();
M.Map.addControl(new SMap.Control.Zoom());
M.Map.addControl(new SMap.Control.Mouse(SMap.MOUSE_PAN));
M.Map.addControl(new SMap.Control.Mouse(SMap.MOUSE_ZOOM));
M.Map.addControl(new SMap.Control.Mouse(SMap.MOUSE_WHEEL));
M.Map.addControl(new SMap.Control.Pointer());
M.Map.addControl(new SMap.Control.Selection());
M.Map.addControl(new SMap.Control.Keyboard());
M.Map.addControl(new SMap.Control.Scale());
M.Map.addControl(new SMap.Control.Sync());
// vrstva pro body
M.Markers = new SMap.Layer.Marker();
M.Map.addLayer(M.Markers);
M.Markers.enable();
// vrstva pro trasu
M.Geometry = new SMap.Layer.Geometry();
M.Map.addLayer(M.Geometry);
M.Geometry.enable();
})();
/**
* Příprava listenerů
*/
(function () {
var signals = M.Map.getSignals();
signals.addListener(window, "geometry-click", createPoint);
signals.addListener(window, "map-click", createPoint);
signals.addListener(window, "marker-drag-stop", dragStop);
})();
/**
* Proměnné trasy
*/
var points = [], routes = [];
var codes = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
var waiting = 0;
/**
* Dokončování výpočtů
*/
function unwait()
{
if (waiting > 0) { waiting--; }
if (waiting == 0)
{
centerMap();
if (options.update != undefined) { options.update(that); }
}
}
/**
* Centrování mapy
*/
function centerMap()
{
if (points.length > 1)
{
var coords = [];
for (var i = 0; i < points.length; i++) {
coords.push(points[i].getCoords());
}
var centerZoom = M.Map.computeCenterZoom(coords, true);
M.Map.setCenterZoom(centerZoom[0], centerZoom[1]);
}
else
{
M.Map.setCenterZoom(M.Center, options.zoom)
}
}
/**
* Vytvoření pinu
*/
function createPin()
{
var markerEl = JAK.mel("div");
var imgEl = JAK.mel("img", { src: "drop-blue.png" });
markerEl.appendChild(imgEl);
var titleEl = JAK.mel("div", {}, { position: "absolute", left: "0px", top: "2px", textAlign: "center", width: "22px", color: "white", fontWeight: "bold" });
markerEl.appendChild(titleEl);
return {
element: markerEl,
setTitle: function (t) { titleEl.innerHTML = t; }
};
}
/**
* Vytvoření značky
* @param {any} event
*/
function createMarker(event)
{
var coords = SMap.Coords.fromEvent(event, M.Map);
var pin = createPin();
var index = 0;
var marker = new SMap.Marker(coords, null, { url: pin.element });
marker.decorate(SMap.Marker.Feature.Shadow);
marker.decorate(SMap.Marker.Feature.Draggable);
marker.index = function (i)
{
if (i != undefined) { index = i; pin.setTitle(codes[index]); }
return index;
};
M.Markers.addMarker(marker);
return marker;
}
/**
* Vytvoření bodu po kliknutí
* @param {any} e
*/
var bouncing = false;
var debounceInterval = 20;
function createPoint(e)
{
// debouncing geometry-click vs map-click kvůli duplicitě
if (e.type == "geometry-click")
{
bouncing = true;
setTimeout(function () {
bouncing = false;
}, debounceInterval);
insertPoint(e);
}
else
{
setTimeout(function () {
if (!bouncing) { createEndPoint(e); }
}, debounceInterval / 2);
}
}
/**
* Vytvoření koncového bodu
* @param {any} e
*/
function createEndPoint(e)
{
var event = e.data.event;
var marker = createMarker(event);
var index = points.length;
marker.index(index);
points.push(marker);
createRoutes(index);
requestLocation(marker);
}
/**
* Přesunutí bodu
* @param {any} e
*/
function dragStop(e)
{
createRoutes(e.target.index());
requestLocation(e.target);
}
/**
* Vložení průjezdního bodu
* @param {any} e
*/
function insertPoint(e)
{
var event = e.data.event;
var route = e.target;
var index = route.end.index();
var marker = createMarker(event);
marker.index(index);
points.splice(index, 0, marker);
for (var i = index + 1; i < points.length; i++)
{
points[i].index(i);
}
routes.splice(index, 0, undefined);
createRoutes(index);
requestLocation(marker);
}
/**
* Vytvoření obou tras - do bodu a z něho
* @param {any} index
*/
function createRoutes(index)
{
if (index > 0)
{
createRoute(index);
}
if (points.length - 1 > index)
{
createRoute(index + 1);
}
}
/**
* Vytvoření trasy
* @param {any} index
*/
function createRoute(index)
{
var start = points[index - 1];
var end = points[index];
var coords = [start.getCoords(), end.getCoords()];
var routeOptions = { altitude: false };
if (options.avoidTolls == true) { routeOptions.toll = "free"; }
waiting++;
new SMap.Route(coords, function (result) {
// smazání staré trasy
if (routes[index - 1] != undefined)
{
M.Geometry.removeGeometry(routes[index - 1]);
}
// vytvoření nové
var route = routeResult(result);
route.start = start;
route.end = end;
routes[index - 1] = route;
unwait();
}, routeOptions);
}
/**
* Zpracování výsledku trasy
* @param {any} result
*/
function routeResult(result)
{
if (options.color == undefined) { options.color = "#0930B4"; }
if (options.stroke == undefined) { options.stroke = "#7395F8"; }
var data = result.getResults();
var coords = data.geometry;
var geometry = new SMap.Geometry(SMap.GEOMETRY_POLYLINE, null, coords, {
color: options.color,
opacity: 0.7,
outlineColor: options.stroke,
outlineOpacity: 0.3,
outlineWidth: 3,
width: 5,
});
geometry.length = data.length / 1000;
geometry.time = (data.time / 60).toFixed(1) * 1;
M.Geometry.addGeometry(geometry);
return geometry;
}
/**
* Získání lokace z bodu
* @param {any} point
*/
function requestLocation(point)
{
waiting++;
new SMap.Geocoder.Reverse(point.getCoords(), function (result) {
var data = result.getResults().items;
var parsed = {
muni: data.find(function (x) { return x.type == "muni" }),
coun: data.find(function (x) { return x.type == "coun" }),
osmm: data.find(function (x) { return x.type == "osmm" }),
osmc: data.find(function (x) { return x.type == "osmc" }),
}
var location = {
foreign: false
}
if (parsed.muni != undefined && parsed.coun != undefined)
{
location.town = parsed.muni.name;
location.country = parsed.coun.name;
if (parsed.coun.name == "Česko")
{
location.label = result.getResults().label;
}
else
{
location.label = location.town + ', ' + location.country;
location.foreign = true;
}
}
else
{
location.town = parsed.osmm.name;
location.country = parsed.osmc.name;
location.label = location.town + ', ' + location.country;
location.foreign = true;
}
point.location = location;
unwait();
});
}
/**
* Veřejné metody pro práci s mapou
*/
this.getRouteData = function ()
{
var out = {};
if (routes.length > 0)
{
out.start = routes[0].start.location.label;
out.pres = [];
out.cil = routes[routes.length - 1].end.location.label;
out.celkem = { delka_km: 0, cas_min: 0 };
out.useky = [];
for (var i = 0; i < routes.length; i++)
{
var route = routes[i];
out.useky.push({
z: route.start.location.label,
do: route.end.location.label,
delka_km: route.length,
cas_min: route.time
});
out.celkem.delka_km += route.length;
out.celkem.cas_min += route.time;
if (i < routes.length - 1)
{
out.pres.push(route.end.location.label);
}
}
}
return out;
}
this.getRouteJSON = function () { return JSON.stringify(that.getRouteData()); }
this.isReady = function () { return waiting == 0; }
this.reset = function ()
{
M.Geometry.removeAll();
M.Markers.removeAll();
points = [];
routes = [];
waiting = 0;
centerMap();
}
}
return SRouteMap;
})();
/**
* Jan Pecha
* http://pecha.it/
*/
var GRouteMap = (function () {
/**
* Mapa
* @param {Object} options
*/
function GRouteMap(options) {
var that = this;
var options = options;
var M = {};
// MapLoader
MapLoader.ready(function () {
init();
initListeners();
});
/**
* Inicializace Google Maps API
*/
function init() {
if (options.center == undefined) { options.center = { lng: 14.395432, lat: 50.100604 }; }
if (options.zoom == undefined) { options.zoom = 9; }
if (options.color == undefined) { options.color = "#0930B4"; }
if (options.stroke == undefined) { options.stroke = "#7395F8"; }
M = {
Map: new google.maps.Map(
document.getElementById(options.elementId),
{
zoom: options.zoom,
center: options.center,
mapTypeControl: false,
streetViewControl: false,
fullscreenControl: false
}
),
Service: new google.maps.DirectionsService(),
Renderer: new google.maps.DirectionsRenderer({
draggable: true,
polylineOptions: {
strokeColor: options.color,
icons: [
{
icon: {
path: google.maps.SymbolPath.CIRCLE,
scale: 4,
},
offset: '0%',
},
{
icon: {
path: google.maps.SymbolPath.CIRCLE,
scale: 4,
},
offset: '100%',
}
]
}
})
};
}
/**
* Příprava listenerů
*/
function initListeners() {
M.Map.addListener('click', createEndPoint);
M.Renderer.addListener('directions_changed', function () {
updateRoute(M.Renderer.getDirections());
});
}
/**
* Proměnné trasy
*/
var points = [];
var codes = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
var startMarker;
var endMarker;
var result;
/**
* Vytvoření bodu po kliknutí a případná úprava trasy
* @param {Event} e
*/
function createEndPoint(e) {
let point = { lat: e.latLng.lat(), lng: e.latLng.lng() };
let marker = new google.maps.Marker({
position: point,
label: {
color: 'white',
text: codes[points.length == 0 ? (startMarker ? 1 : 0) : (points.length % codes.length)]
},
map: M.Map,
draggable: true,
});
length++;
if (points.length == 0) {
if (!startMarker) {
startMarker = marker;
}
else {
endMarker = marker;
createRoute([startMarker.position, endMarker.position]);
}
}
else {
endMarker = marker;
points.push(marker.position);
createRoute(points);
}
}
/**
* Vytvoření trasy z pole bodů
* @param {Array} points
*/
function createRoute(points) {
if (options.avoidHighways == undefined) { options.avoidHighways = false; }
if (options.avoidTolls == undefined) { options.avoidTolls = false; }
M.Service.route(
{
origin: points[0],
waypoints: points.slice(1, points.length - 1),
destination: points[points.length - 1],
travelMode: 'DRIVING',
avoidHighways: options.avoidHighways,
avoidTolls: options.avoidTolls
},
function (response, status) {
if (status === 'OK') {
if (startMarker) { startMarker.setVisible(false); }
if (endMarker) { endMarker.setVisible(false); }
M.Renderer.setDirections(response);
M.Renderer.setMap(M.Map);
} else {
M.Renderer.setMap(null);
}
},
);
}
/**
* Bod na LatLng
* @param {any} point
*/
function getPoint(point) {
let coords = point.location ? (point.location.location ? point.location.location : point.location) : point;
return {
location: {
lat: typeof (coords.lat) == 'function' ? coords.lat() : coords.lat,
lng: typeof (coords.lng) == 'function' ? coords.lng() : coords.lng,
}
};
}
/**
* Zpracování trasy
* @param {DirectionsResult} directions
*/
function updateRoute(directions) {
result = directions;
// uložení průchozích bodů
let request = result.request;
let waypoints = [];
request.waypoints.forEach(function (waypoint) {
waypoints.push(getPoint(waypoint));
});
points = [].concat(
[getPoint(request.origin)],
waypoints,
[getPoint(request.destination)]
);
// pokud vznikl waypoint přetažením trasy -> znovu vypočítat trasu, aby se rozdělila na úseky
if (result.request.waypoints.length + 1 > result.routes[0].legs.length) {
createRoute(points);
} else {
if (options.update != undefined) { options.update(that); }
}
}
/**
* Veřejné metody pro práci s mapou
*/
this.getRouteData = function () {
var out = {};
if (result)
{
var routes = result.routes[0].legs;
if (routes.length > 0)
{
out.start = routes[0].start_address;
out.pres = [];
out.cil = routes[routes.length - 1].end_address;
out.celkem = { delka_km: 0, cas_min: 0 };
out.useky = [];
for (var i = 0; i < routes.length; i++)
{
var route = routes[i];
out.useky.push({
z: route.start_address,
do: route.end_address,
delka_km: route.distance.value / 1000,
cas_min: (route.duration.value / 60).toFixed(2) * 1
});
out.celkem.delka_km += route.distance.value / 1000;
out.celkem.cas_min += (route.duration.value / 60).toFixed(2) * 1;
if (i < routes.length - 1)
{
out.pres.push(route.end_address);
}
}
}
}
return out;
}
this.getRouteJSON = function () {
return JSON.stringify(this.getRouteData());
}
this.reset = function () {
points = [];
startMarker = undefined;
endMarker = undefined;
result = undefined;
if (options.update != undefined) { options.update(that); }
M.Renderer.setMap(null);
M.Map.setCenter(options.center);
M.Map.setZoom(options.zoom);
}
}
return GRouteMap;
})();
Tato stránka slouží pro srovnání implementace plánovačů tras postavených na Mapy.cz API a Google Maps API.
Trasu lze vytvořit vyznačením počátečního a koncového bodu v mapě. Dalším kliknutím do mapy je možné přidat nový koncový bod nebo kliknutím na trasu vložit průjezdní bod. Všechny průjezdní i koncové body jsou přesouvatelné pomocí tzv. "drag&drop".
Výstup vypočtené trasy včetně adres všech míst, vzdáleností a odhadované doby trvání si můžete zobrazit ve formátu JSON na záložce "Výstup trasy". Samotný způsob implementace plánovače trasy v jazyce JavaScript postaveném na daném API si můžete prohlédnout na záložce "Zdrojový kód".
Případné opětovné použití kódu nebo jeho součástí jen s výslovným souhlasem autora.