(function () {
var mapaEl = document.getElementById('map');
var dataEl = document.getElementById('stari-data');
if (!mapaEl || !dataEl || typeof L === 'undefined') {
return;
}
var stari = JSON.parse(dataEl.textContent || '{}');
var maxMesicu = parseInt(mapaEl.getAttribute('data-max'), 10) || 24;
var maxPrideleni = parseInt(mapaEl.getAttribute('data-prideleni'), 10) || 12;
var geojsonUrl = mapaEl.getAttribute('data-geojson');
var obvodId = mapaEl.getAttribute('data-obvod');
var prihlaseny = mapaEl.getAttribute('data-prihlaseny') === '1';
var rezim = mapaEl.getAttribute('data-filtr');
if (!prihlaseny || (rezim !== 'stari' && rezim !== 'nedokoncene')) {
rezim = 'obvody';
}
var ZELENA = [27, 158, 62];
var ZLUTA = [230, 184, 0];
var CERVENA = [198, 40, 40];
var SEDA = '#9e9e9e';
var SEDA_HRANICE = '#616161';
var MODRA = '#2652a8';
var MODRA_PLOCHA = '#c5ddf6';
function mix(a, b, t) {
return [
Math.round(a[0] + (b[0] - a[0]) * t),
Math.round(a[1] + (b[1] - a[1]) * t),
Math.round(a[2] + (b[2] - a[2]) * t),
];
}
function rgb(kanaly) {
return 'rgb(' + kanaly[0] + ',' + kanaly[1] + ',' + kanaly[2] + ')';
}
function barvaStari(mesice, stupnice) {
var max = stupnice || maxMesicu;
var t = mesice == null ? 1 : Math.max(0, Math.min(mesice / max, 1));
if (t < 0.5) {
return rgb(mix(ZELENA, ZLUTA, t / 0.5));
}
return rgb(mix(ZLUTA, CERVENA, (t - 0.5) / 0.5));
}
function infoObvodu(feature) {
if (!feature.properties || feature.properties.number == null) {
return null;
}
return stari[String(feature.properties.number)] || null;
}
function style(feature) {
var info = infoObvodu(feature);
if (rezim === 'obvody') {
return {
fillColor: MODRA_PLOCHA,
color: '#1d4f91',
weight: 2,
opacity: 1,
fillOpacity: 0.28,
};
}
if (rezim === 'nedokoncene') {
if (info && info.probiha) {
var barvaPrideleni = barvaStari(info.prideleni, maxPrideleni);
return {
fillColor: barvaPrideleni,
color: barvaPrideleni,
weight: 2,
opacity: 1,
fillOpacity: 0.55,
};
}
return {
fillColor: '#b0bec5',
color: '#90a4ae',
weight: 1,
opacity: 0.4,
dashArray: '3',
fillOpacity: 0.04,
};
}
var mesice = info ? info.mesice : null;
var barva = barvaStari(mesice);
if (info && info.probiha) {
return {
fillColor: SEDA,
color: SEDA_HRANICE,
weight: 2,
opacity: 1,
fillOpacity: 0.72,
};
}
return {
fillColor: barva,
color: barva,
weight: 2,
opacity: 1,
fillOpacity: 0.55,
};
}
var API_KEY = 'Uw8gm6JPZpnT3GfNnh8adARpQI-WBGy6QaY9g6VhD74';
var mapyCZ = L.tileLayer('https://api.mapy.cz/v1/maptiles/basic/256/{z}/{x}/{y}?apikey=' + API_KEY, {
minZoom: 0,
maxZoom: 19,
attribution: '© Seznam.cz a.s. a další',
});
var mapyCZletecka = L.tileLayer('https://api.mapy.cz/v1/maptiles/aerial/256/{z}/{x}/{y}?apikey=' + API_KEY, {
minZoom: 0,
maxZoom: 19,
attribution: '© Seznam.cz a.s. a další',
});
var osm = L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', {
maxZoom: 19,
attribution: '© OpenStreetMap',
});
var map = L.map(mapaEl, {
center: [50.853501146, 14.8425],
zoom: 13,
layers: [mapyCZ],
});
L.control.layers({
'Mapy.cz': mapyCZ,
'Mapy.cz (letecká)': mapyCZletecka,
'OpenStreetMap': osm,
}).addTo(map);
var LogoControl = L.Control.extend({
options: { position: 'bottomleft' },
onAdd: function () {
var container = L.DomUtil.create('div');
var link = L.DomUtil.create('a', '', container);
link.setAttribute('href', 'http://mapy.cz/');
link.setAttribute('target', '_blank');
link.innerHTML = '
';
L.DomEvent.disableClickPropagation(link);
return container;
},
});
new LogoControl().addTo(map);
var legendaEl = null;
var Legenda = L.Control.extend({
options: { position: 'bottomright' },
onAdd: function () {
legendaEl = L.DomUtil.create('div', 'stari-legenda');
legendaEl.innerHTML = obsahLegendy();
L.DomEvent.disableClickPropagation(legendaEl);
return legendaEl;
},
});
new Legenda().addTo(map);
var filtrTlacitka = [];
var Filtr = L.Control.extend({
options: { position: 'topright' },
onAdd: function () {
var div = L.DomUtil.create('div', 'mapa-filtr');
div.innerHTML =
'' +
'' +
'';
L.DomEvent.disableClickPropagation(div);
filtrTlacitka = div.querySelectorAll('button');
filtrTlacitka.forEach(function (tlacitko) {
tlacitko.addEventListener('click', function () {
nastavRezim(tlacitko.getAttribute('data-rezim'));
});
});
return div;
},
});
if (prihlaseny) {
new Filtr().addTo(map);
}
function textMesicu(mesice) {
if (mesice == null) {
return '—';
}
return mesice + ' měs.';
}
function textBadge(mesice) {
return mesice == null ? '—' : mesice + ' měs.';
}
function barvaTextu(mesice, stupnice) {
var max = stupnice || maxMesicu;
var t = mesice == null ? 1 : Math.max(0, Math.min(mesice / max, 1));
return t > 0.72 ? '#fff' : '#1a1a1a';
}
function htmlKolecko(text, mesice, sede, stupnice) {
var barva = sede ? SEDA : barvaStari(mesice, stupnice);
var okraj = sede ? SEDA_HRANICE : barva;
var textBarva = sede ? '#1a1a1a' : barvaTextu(mesice, stupnice);
return '
' + text + '
';
}
function htmlZnacky(cislo, info) {
if (rezim === 'obvody') {
return '';
}
if (rezim === 'nedokoncene') {
var prideleni = info ? info.prideleni : null;
var barvaPrideleni = barvaStari(prideleni, maxPrideleni);
return '' +
htmlKolecko(cislo, prideleni, false, maxPrideleni) +
'
' + textBadge(prideleni) + '
' +
'
';
}
var mesice = info ? info.mesice : null;
var html = '' + htmlKolecko(cislo, mesice, !!(info && info.probiha));
if (!info || !info.probiha) {
var barva = barvaStari(mesice);
html += '
' + textBadge(mesice) + '
';
}
return html + '
';
}
function htmlSkupiny(pocet, mesice, sede, stupnice) {
return '' +
htmlKolecko(pocet + 'x', mesice, sede, stupnice) +
'
';
}
function vytvorSkupinu() {
return L.markerClusterGroup({
showCoverageOnHover: false,
spiderfyOnMaxZoom: true,
zoomToBoundsOnClick: true,
maxClusterRadius: 46,
disableClusteringAtZoom: 17,
iconCreateFunction: function (cluster) {
var pocet = cluster.getChildCount();
if (rezim === 'obvody') {
return L.divIcon({
className: 'obvod-skupina',
html: '',
iconSize: [44, 44],
iconAnchor: [22, 22],
});
}
if (rezim === 'nedokoncene') {
var nejPrideleni = 0;
var bezPrideleni = false;
cluster.getAllChildMarkers().forEach(function (marker) {
if (marker.odPrideleni == null) {
bezPrideleni = true;
} else if (marker.odPrideleni > nejPrideleni) {
nejPrideleni = marker.odPrideleni;
}
});
return L.divIcon({
className: 'obvod-skupina',
html: htmlSkupiny(pocet, bezPrideleni ? null : nejPrideleni, false, maxPrideleni),
iconSize: [44, 44],
iconAnchor: [22, 22],
});
}
var nej = 0;
var bezData = false;
var maHotovy = false;
cluster.getAllChildMarkers().forEach(function (marker) {
if (marker.obvodProbiha) {
return;
}
maHotovy = true;
if (marker.obvodMesice == null) {
bezData = true;
} else if (marker.obvodMesice > nej) {
nej = marker.obvodMesice;
}
});
var sede = !maHotovy;
return L.divIcon({
className: 'obvod-skupina',
html: htmlSkupiny(pocet, sede || bezData ? null : nej, sede),
iconSize: [44, 44],
iconAnchor: [22, 22],
});
},
});
}
var znacky = null;
function popupHtml(cislo, info) {
if (!prihlaseny) {
return 'Obvod č. ' + cislo + '';
}
var html = 'Obvod č. ' + cislo + '
';
if (!info || info.vraceno == null) {
html += 'Zatím bez propracování';
} else {
html += 'Naposledy propracováno ' + info.vraceno + ' (' + textMesicu(info.mesice) + ')';
}
if (info && info.probiha) {
html += '
Přiděleno ' + (info.prideleniDatum || '—') + ' (' + textMesicu(info.prideleni) + ')';
}
if (info && info.url) {
html += '
Otevřít obvod';
}
return html;
}
function jeLatLng(hodnota) {
return hodnota && typeof hodnota.lat === 'number' && typeof hodnota.lng === 'number';
}
function prstence(latlngs) {
if (!latlngs || !latlngs.length) {
return [];
}
if (jeLatLng(latlngs[0])) {
return [latlngs.map(function (bod) { return [bod.lng, bod.lat]; })];
}
if (jeLatLng(latlngs[0][0])) {
return latlngs.map(function (prstenec) {
return prstenec.map(function (bod) { return [bod.lng, bod.lat]; });
});
}
var nej = [];
var nejPlocha = -1;
latlngs.forEach(function (polygon) {
var rings = prstence(polygon);
var plocha = rings.length ? Math.abs(plochaPrstence(rings[0])) : 0;
if (plocha > nejPlocha) {
nejPlocha = plocha;
nej = rings;
}
});
return nej;
}
function plochaPrstence(prstenec) {
var plocha = 0;
for (var i = 0, j = prstenec.length - 1; i < prstenec.length; j = i++) {
plocha += prstenec[i][0] * prstenec[j][1] - prstenec[j][0] * prstenec[i][1];
}
return plocha;
}
function vzdalenostUsecky(px, py, a, b) {
var x = a[0];
var y = a[1];
var dx = b[0] - x;
var dy = b[1] - y;
if (dx !== 0 || dy !== 0) {
var t = ((px - x) * dx + (py - y) * dy) / (dx * dx + dy * dy);
if (t > 1) {
x = b[0];
y = b[1];
} else if (t > 0) {
x += dx * t;
y += dy * t;
}
}
dx = px - x;
dy = py - y;
return dx * dx + dy * dy;
}
function vzdalenostPolygonu(x, y, prstenceBodu) {
var uvnitr = false;
var nejmensi = Infinity;
prstenceBodu.forEach(function (prstenec) {
for (var i = 0, j = prstenec.length - 1; i < prstenec.length; j = i++) {
var a = prstenec[i];
var b = prstenec[j];
if ((a[1] > y) !== (b[1] > y) && x < ((b[0] - a[0]) * (y - a[1])) / (b[1] - a[1]) + a[0]) {
uvnitr = !uvnitr;
}
nejmensi = Math.min(nejmensi, vzdalenostUsecky(x, y, a, b));
}
});
return (uvnitr ? 1 : -1) * Math.sqrt(nejmensi);
}
function bunka(x, y, h, prstenceBodu) {
var d = vzdalenostPolygonu(x, y, prstenceBodu);
return { x: x, y: y, h: h, d: d, max: d + h * Math.SQRT2 };
}
function vlozHaldu(halda, bunkaBodu) {
halda.push(bunkaBodu);
var i = halda.length - 1;
while (i > 0) {
var rodic = (i - 1) >> 1;
if (halda[rodic].max >= halda[i].max) {
break;
}
var tmp = halda[rodic];
halda[rodic] = halda[i];
halda[i] = tmp;
i = rodic;
}
}
function vyberHaldu(halda) {
var vrchol = halda[0];
var posledni = halda.pop();
if (halda.length && vrchol !== posledni) {
halda[0] = posledni;
var i = 0;
while (true) {
var levy = i * 2 + 1;
var pravy = levy + 1;
var nej = i;
if (levy < halda.length && halda[levy].max > halda[nej].max) {
nej = levy;
}
if (pravy < halda.length && halda[pravy].max > halda[nej].max) {
nej = pravy;
}
if (nej === i) {
break;
}
var tmp = halda[i];
halda[i] = halda[nej];
halda[nej] = tmp;
i = nej;
}
}
return vrchol;
}
function teziste(prstenceBodu) {
var prstenec = prstenceBodu[0];
var plocha = 0;
var x = 0;
var y = 0;
for (var i = 0, j = prstenec.length - 1; i < prstenec.length; j = i++) {
var f = prstenec[i][0] * prstenec[j][1] - prstenec[j][0] * prstenec[i][1];
x += (prstenec[i][0] + prstenec[j][0]) * f;
y += (prstenec[i][1] + prstenec[j][1]) * f;
plocha += f;
}
if (plocha === 0) {
return [prstenec[0][0], prstenec[0][1]];
}
return [x / (3 * plocha), y / (3 * plocha)];
}
function bodUvnitr(prstenceBodu) {
var minX = Infinity;
var minY = Infinity;
var maxX = -Infinity;
var maxY = -Infinity;
prstenceBodu[0].forEach(function (bod) {
minX = Math.min(minX, bod[0]);
minY = Math.min(minY, bod[1]);
maxX = Math.max(maxX, bod[0]);
maxY = Math.max(maxY, bod[1]);
});
var sirka = maxX - minX;
var vyska = maxY - minY;
var krok = Math.min(sirka, vyska);
if (krok === 0) {
return [minX, minY];
}
var pul = krok / 2;
var halda = [];
for (var x = minX; x < maxX; x += krok) {
for (var y = minY; y < maxY; y += krok) {
vlozHaldu(halda, bunka(x + pul, y + pul, pul, prstenceBodu));
}
}
var stred = teziste(prstenceBodu);
var nej = bunka(stred[0], stred[1], 0, prstenceBodu);
var obdelnik = bunka(minX + sirka / 2, minY + vyska / 2, 0, prstenceBodu);
if (obdelnik.d > nej.d) {
nej = obdelnik;
}
var presnost = Math.max(krok / 40, 0.00005);
var pojistka = 0;
while (halda.length && pojistka < 8000) {
var aktualni = vyberHaldu(halda);
pojistka++;
if (aktualni.d > nej.d) {
nej = aktualni;
}
if (aktualni.max - nej.d <= presnost) {
continue;
}
var h = aktualni.h / 2;
vlozHaldu(halda, bunka(aktualni.x - h, aktualni.y - h, h, prstenceBodu));
vlozHaldu(halda, bunka(aktualni.x + h, aktualni.y - h, h, prstenceBodu));
vlozHaldu(halda, bunka(aktualni.x - h, aktualni.y + h, h, prstenceBodu));
vlozHaldu(halda, bunka(aktualni.x + h, aktualni.y + h, h, prstenceBodu));
}
return [nej.x, nej.y];
}
function vnitrniBod(layer) {
var rings = prstence(layer.getLatLngs());
if (!rings.length) {
return layer.getBounds().getCenter();
}
var bod = bodUvnitr(rings);
if (vzdalenostPolygonu(bod[0], bod[1], rings) <= 0) {
return layer.getBounds().getCenter();
}
return L.latLng(bod[1], bod[0]);
}
function onEachFeature(feature, layer) {
var cislo = feature.properties && feature.properties.number != null ? feature.properties.number : '';
var info = infoObvodu(feature);
var stred = vnitrniBod(layer);
var nedokonceny = !!(info && info.probiha);
if (rezim !== 'nedokoncene' || nedokonceny) {
var marker = L.marker(stred, {
icon: L.divIcon({
className: 'obvod-znacka',
html: htmlZnacky(cislo, info),
iconSize: [58, 46],
iconAnchor: [29, 14],
}),
interactive: false,
keyboard: false,
});
marker.obvodMesice = info ? info.mesice : null;
marker.odPrideleni = info ? info.prideleni : null;
marker.obvodProbiha = nedokonceny;
znacky.addLayer(marker);
}
layer.bindPopup(popupHtml(cislo, info));
layer.on({
mouseover: function (e) {
e.target.setStyle({ weight: 4, fillOpacity: 0.8 });
e.target.bringToFront();
},
mouseout: function (e) {
geojson.resetStyle(e.target);
},
click: function (e) {
map.fitBounds(e.target.getBounds(), { padding: [24, 24] });
},
});
}
var geojson = null;
var geoData = null;
function filtrObvodu(feature) {
if (!obvodId) {
return true;
}
return feature.properties && String(feature.properties.number) === String(obvodId);
}
function obsahLegendy() {
if (rezim === 'nedokoncene') {
return 'Měsíce od začátku přidělení
' +
'' +
'0' + Math.round(maxPrideleni / 2) + '' + maxPrideleni + '+
';
}
return 'Měsíce od posledního propracování
' +
'' +
'0' + Math.round(maxMesicu / 2) + '' + maxMesicu + '+
' +
' právě se propracovává
';
}
function oznacFiltr() {
filtrTlacitka.forEach(function (tlacitko) {
tlacitko.classList.toggle('is-active', tlacitko.getAttribute('data-rezim') === rezim);
});
if (legendaEl) {
legendaEl.style.display = rezim === 'obvody' ? 'none' : '';
if (rezim !== 'obvody') {
legendaEl.innerHTML = obsahLegendy();
}
}
}
function prekresli(poprve) {
if (geojson) {
map.removeLayer(geojson);
}
if (znacky) {
map.removeLayer(znacky);
}
znacky = vytvorSkupinu();
geojson = L.geoJSON(geoData, {
style: style,
filter: filtrObvodu,
onEachFeature: onEachFeature,
}).addTo(map);
znacky.addTo(map);
oznacFiltr();
if (poprve && geojson.getLayers().length) {
map.fitBounds(geojson.getBounds(), { padding: [12, 12], animate: false });
}
}
function nastavRezim(novy) {
if (!prihlaseny || (novy !== 'stari' && novy !== 'nedokoncene')) {
novy = 'obvody';
}
if (novy === rezim) {
return;
}
rezim = novy;
prekresli(false);
if (window.history && window.history.replaceState) {
var url = new URL(window.location.href);
if (rezim === 'obvody') {
url.searchParams.delete('filtr');
} else {
url.searchParams.set('filtr', rezim);
}
window.history.replaceState(null, '', url);
}
}
$.getJSON(geojsonUrl, function (data) {
geoData = data;
prekresli(true);
});
L.control.locate({
flyTo: true,
strings: {
title: 'Moje poloha',
metersUnit: 'metrů',
feetUnit: 'feet',
popup: 'Nacházíš se v okolí {distance} {unit} od tohoto bodu.',
outsideMapBoundsMsg: 'Zdá se, že jsi mimo oblast mapy.',
},
}).addTo(map);
})();