/**
* tilda-map добавляет на страницу Yandex- или Google-карты. В блоки передаются пользователями API-ключи,
* которые в этом скрипте принимаются в качестве аргументов, и создают скрипт с апи ключом, добавляя его на страницу.
* Здесь так же устаналиваются доп. настройки для карты: центрирование карты, балуны, язык, и т.д.
*/
/* eslint-disable-next-line no-unused-vars */
function t_appendGoogleMap(recid, key) {
if (typeof google === 'object' && typeof google.maps === 'object') {
t_handleGoogleApiReady(recid);
} else if (!window.googleapiiscalled) {
var runfunc = 'window.t_handleGoogleApiReady_' + recid + ' = function () { t_handleGoogleApiReady("' + recid + '") }';
eval(runfunc);
var langPreferences = '';
var mapLang = '';
var tildaMapElement = document.querySelector('#rec' + recid + ' .t-map');
var tildaMapElLang = tildaMapElement.getAttribute('data-map-language');
if (tildaMapElement) {
mapLang = tildaMapElLang || '';
}
if (mapLang && mapLang.length === 2) {
langPreferences = '&language=' + mapLang;
}
var script = document.createElement('script');
script.type = 'text/javascript';
var mapKey = key ? key.trim() : '';
script.src = 'https://maps.google.com/maps/api/js?key=' + mapKey + '&callback=t_handleGoogleApiReady_' + recid + langPreferences;
document.body.appendChild(script);
window.googleapiiscalled = true;
} else {
setTimeout(function () {
t_appendGoogleMap(recid, key);
}, 1000);
}
}
function t_handleGoogleApiReady(recid) {
var gmaps = document.querySelectorAll('#rec' + recid + ' .t-map');
if (!gmaps.length) return false;
Array.prototype.forEach.call(gmaps, function (gmap) {
var arMarkers = window['arMapMarkers' + recid];
window.isDragMap = !window.isMobile;
var mapStyleAttr = gmap.getAttribute('data-map-style');
var mapColorAttr = gmap.getAttribute('data-map-color');
var mapModeAttr = gmap.getAttribute('data-map-mode');
var mapZoomAttr = gmap.getAttribute('data-map-zoom');
var myLatLng = arMarkers.length > 0 ? new google.maps.LatLng(parseFloat(arMarkers[0].lat), parseFloat(arMarkers[0].lng)) : false;
var myOptions = {
zoom: parseInt(mapZoomAttr, 10),
center: myLatLng,
scrollwheel: false,
gestureHandling: 'cooperative',
zoomControl: true,
styles: getMapStyle(mapModeAttr, mapStyleAttr, mapColorAttr)
};
function getMapStyle(mode, style, color) {
// Оставляем обратную совместимость
if (mode && !color) {
return style ? JSON.parse(style) : [];
}
if (mode && color) {
var hsl = t_map_hexToHsl(color);
// В апи гугла значения от -100 до 100, поэтому мапим диапазон
var saturation = hsl[1] * 2 - 100;
var lightness = hsl[2] * 2 - 100;
var invert = mode === 'bw_dark';
return [{
featureType: 'all',
elementType: 'all',
stylers: [
{visibility: 'simplified'},
{hue: color},
{saturation: saturation},
// если темная карта, то инвертируем яркость из-за особенностей работы настройки invert_lightness
{lightness: invert ? -lightness : lightness},
{invert_lightness: invert},
]
}];
}
}
var map = new google.maps.Map(gmap, myOptions);
var bounds = new google.maps.LatLngBounds();
// Добавляем кастомный svg маркер тк в апи гугла нет возможности менять цвет маркера
function getSvgMarker(color) {
return {
path: 'M182.9,551.7c0,0.1,0.2,0.3,0.2,0.3S358.3,283,358.3,194.6c0-130.1-88.8-186.7-175.4-186.9 C96.3,7.9,7.5,64.5,7.5,194.6c0,88.4,175.3,357.4,175.3,357.4S182.9,551.7,182.9,551.7z M122.2,187.2c0-33.6,27.2-60.8,60.8-60.8 c33.6,0,60.8,27.2,60.8,60.8S216.5,248,182.9,248C149.4,248,122.2,220.8,122.2,187.2z',
fillColor: color || '#ea4335',
fillOpacity: 1,
strokeColor: '#5e5e5e',
strokeOpacity: .5,
strokeWeight: 1,
rotation: 0,
scale: .075,
anchor: new google.maps.Point(180, 555),
};
}
// Добавляем смещение для маркера из настроек блока или прописываем свое дефолтное
function getAnchor(marker) {
if (marker.offset) {
var arr = marker.offset.replace(/\s/g, '').split(',');
// инвертирум значения чтобы добится аналогичного поведения как в яндекс картах
var x = -1 * +arr[0];
var y = -1 * +arr[1];
return new google.maps.Point(x, y);
}
return new google.maps.Point(0, 48);
}
Array.prototype.forEach.call(arMarkers, function (el) {
var myLatLng = new google.maps.LatLng(parseFloat(el.lat), parseFloat(el.lng));
var icon = {
url:el.url,
size: new google.maps.Size(48, 48),
anchor: getAnchor(el),
};
var marker = new google.maps.Marker({
position: myLatLng,
visible: !el.isHidden,
map: map,
title: el.title,
icon: el.url ? icon : getSvgMarker(el.color),
});
bounds.extend(myLatLng);
if (el.descr || el.title) {
t_map__attachInfoMessage(marker, el.descr, el.title, el.isOpen);
}
});
var mapPathAttr = gmap.getAttribute('data-map-path');
var mapPathColorAttr = gmap.getAttribute('data-map-path-color');
var mapPathWeightAttr = gmap.getAttribute('data-map-path-weight');
if (mapPathAttr !== null && arMarkers.length > 1) {
var path = new google.maps.Polyline({
path: arMarkers.map(function (item) { return new google.maps.LatLng(parseFloat(item.lat), parseFloat(item.lng));}),
geodesic: true,
strokeColor: mapPathColorAttr || '#ff6d61',
strokeWeight: parseInt(mapPathWeightAttr) || 2,
});
path.setMap(map);
}
function t_map__attachInfoMessage(marker, descr, title, isOpen) {
var textarea = document.createElement('textarea');
textarea.innerHTML = descr;
var baloonTitle = title ? '' + title + '' : '';
var baloonDescr = textarea.textContent;
var baloonContent = [baloonTitle, baloonDescr].filter(Boolean).join('
');
var infowindow = new google.maps.InfoWindow({
content: baloonContent
});
if (isOpen) {
infowindow.open(marker.get('map'), marker);
}
marker.addListener('click', function () {
infowindow.open(marker.get('map'), marker);
});
}
if (arMarkers.length > 1) {
map.fitBounds(bounds);
var listener = google.maps.event.addListener(map, 'idle', function () {
if (map.getZoom() > parseInt(mapZoomAttr, 10) || map.getZoom() === 0) {
map.setZoom(parseInt(mapZoomAttr, 10));
}
if (map.getZoom() > 16) {
map.setZoom(16);
}
google.maps.event.removeListener(listener);
});
}
/* Resizing the map for responsive design */
google.maps.event.addDomListener(window, 'resize', function () {
var center = map.getCenter();
var zoom = parseInt(mapZoomAttr, 10);
google.maps.event.trigger(map, 'resize');
map.setCenter(center);
if (arMarkers.length > 0) {
map.fitBounds(bounds);
if (zoom > 0 && (map.getZoom() > zoom || map.getZoom() == 0)) {
map.setZoom(zoom);
}
}
});
gmap.addEventListener('displayChanged', function () {
google.maps.event.trigger(map, 'resize');
});
gmap.addEventListener('sizechange', function () {
google.maps.event.trigger(map, 'resize');
});
});
}
/* eslint-disable-next-line no-unused-vars */
function t_appendYandexMap(recid, key) {
if (typeof ymaps === 'object' && typeof ymaps.Map === 'function') {
t_handleYandexApiReady(recid);
} else if (!window.yandexmapsapiiscalled) {
var runfunc = 'window.t_handleYandexApiReady_' + recid + ' = function () { return t_handleYandexApiReady("' + recid + '") }';
eval(runfunc);
var mapLang = '';
var tildaMapElement = document.querySelector('#rec' + recid + ' .t-map');
var tildaMapElAttr = tildaMapElement.getAttribute('data-map-language');
if (tildaMapElement) {
switch (tildaMapElAttr) {
case 'EN':
mapLang = 'en_US';
break;
default:
mapLang = 'ru_RU';
}
}
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = 'https://api-maps.yandex.ru/2.1/?lang=' + mapLang + '&coordorder=latlong&onload=t_handleYandexApiReady_' + recid;
if (key) {
script.src += '&apikey=' + key;
}
document.body.appendChild(script);
window.yandexmapsapiiscalled = true;
} else {
setTimeout(function () {
t_appendYandexMap(recid, key);
}, 1000);
}
}
function t_handleYandexApiReady(recid) {
var ymapsArr = document.querySelectorAll('#rec' + recid + ' .t-map');
if (!ymapsArr.length) return false;
Array.prototype.forEach.call(ymapsArr, function (ymap) {
var arMarkers = window['arMapMarkers' + recid];
var mapZoomAttr = ymap.getAttribute('data-map-zoom');
window.isDragMap = !window.isMobile;
var myLatLng = arMarkers.length > 0 ? [parseFloat(arMarkers[0].lat), parseFloat(arMarkers[0].lng)] : false;
var myOptions = {
zoom: parseInt(mapZoomAttr, 10),
center: myLatLng,
scrollZoom: false,
controls: ['typeSelector', 'zoomControl'],
drag: window.isDragMap
};
var map = new ymaps.Map(ymap, myOptions);
var eventsPane = map.panes.get('events');
var eventsPaneEl = eventsPane.getElement();
var mobilePanelText = {
EN: 'Use two fingers to move the map',
RU: 'Чтобы переместить карту проведите по ней двумя пальцами',
FR: 'Utilisez deux doigts pour déplacer la carte',
DE: 'Verschieben der Karte mit zwei Fingern',
ES: 'Para mover el mapa, utiliza dos dedos',
PT: 'Use dois dedos para mover o mapa',
UK: 'Переміщуйте карту двома пальцями',
JA: '地図を移動させるには指 2 本で操作します',
ZH: '使用双指移动地图',
PL: 'Przesuń mapę dwoma palcami',
KK: 'Картаны екі саусақпен жылжытыңыз',
IT: 'Utilizza due dita per spostare la mappa',
LV: 'Lai pārvietotu karti, bīdiet to ar diviem pirkstiem',
};
var mobilePanelStyles = {
alignItems: 'center',
boxSizing: 'border-box',
color: 'white',
display: 'flex',
justifyContent: 'center',
fontSize: '22px',
fontFamily: 'Arial,sans-serif',
opacity: '0.0',
padding: '25px',
textAlign: 'center',
transition: 'opacity .3s',
touchAction: 'auto'
};
Array.prototype.forEach.call(Object.keys(mobilePanelStyles), function (name) {
eventsPaneEl.style[name] = mobilePanelStyles[name];
});
map.behaviors.disable('scrollZoom');
if (window.isMobile) {
map.behaviors.disable('drag');
ymaps.domEvent.manager.add(eventsPaneEl, 'touchmove', function (event) {
if (event.get('touches').length === 1) {
eventsPaneEl.style.transition = 'opacity .3s';
eventsPaneEl.style.background = 'rgba(0, 0, 0, .45)';
eventsPaneEl.textContent = mobilePanelText[window.browserLang] || mobilePanelText['EN'];
eventsPaneEl.style.opacity = '1';
}
});
ymaps.domEvent.manager.add(eventsPaneEl, 'touchend', function () {
eventsPaneEl.style.transition = 'opacity .8s';
eventsPaneEl.style.opacity = '0';
});
}
function getIconImageOffset(marker) {
if (marker.url && marker.offset) {
return marker.offset.replace(/\s/g, '').split(',').map(Number);
}
if (marker.url) {
return [0, -48];
}
}
var placemarks = arMarkers.map(function (marker) {
var myLatlng = [parseFloat(marker.lat), parseFloat(marker.lng)];
var textarea = document.createElement('textarea');
textarea.innerHTML = marker.descr;
var baloonTitle = marker.title ? '' + marker.title + '' : '';
var baloonDescr = textarea.textContent;
var baloonContent = [baloonTitle, baloonDescr].filter(Boolean).join('
');
var placemark = new ymaps.Placemark(myLatlng, {
hintContent: marker.title,
balloonContent: baloonContent,
}, {
iconColor: marker.color || undefined,
iconLayout: marker.url ? 'default#imageWithContent' : undefined,
iconImageHref: marker.url || undefined,
iconImageSize: marker.url ? [48, 48] : undefined,
iconImageOffset: getIconImageOffset(marker),
visible: !marker.isHidden
});
return placemark;
});
// Добавляем маркеры в коллекцию, а колекцию на карту
var collection = new ymaps.GeoObjectCollection({});
placemarks.forEach(function(placemark) {
collection.add(placemark);
});
map.geoObjects.add(collection);
// Открывать балун можем только после того как добавили маркер на карту, поэтому проходимся еще раз
placemarks.forEach(function(placemark, index) {
if (arMarkers[index].isOpen) {
placemark.balloon.open();
}
});
var mapPathAttr = ymap.getAttribute('data-map-path');
var mapPathColorAttr = ymap.getAttribute('data-map-path-color');
var mapPathWeightAttr = ymap.getAttribute('data-map-path-weight');
if (arMarkers.length > 1 && mapPathAttr !== null) {
var myPolyline = new ymaps.Polyline(arMarkers.map(function (marker) {
return [parseFloat(marker.lat), parseFloat(marker.lng)];
}), {}, {
// Берем близкие настройки к дефолтным у яндекса
strokeColor: mapPathColorAttr || '#06f',
strokeWidth: parseInt(mapPathWeightAttr, 10) || 1,
strokeOpacity: .85
});
map.geoObjects.add(myPolyline);
}
var mapColorAttr = ymap.getAttribute('data-map-color');
var mapModeAttr = ymap.getAttribute('data-map-mode');
if (mapModeAttr) {
var groundPaneElementChild = ymap.querySelector('ymaps[class$="ground-pane" i] > ymaps');
if (groundPaneElementChild) {
groundPaneElementChild.style.filter = mapModeAttr === 'bw_light' ? 'grayscale(1)' : 'grayscale(1) invert(1)';
}
if (mapColorAttr) {
var groundPaneElement = ymap.querySelector('ymaps[class$="ground-pane" i]');
var coloredDiv = document.createElement('div');
// Добавляем див с цветом в DOM. Он будет находиться внутри карты
coloredDiv.style.opacity = '.15';
coloredDiv.style.backgroundColor = mapColorAttr;
// див делаем большим, чтобы тонирование было видно когда драгаем карту,
// иначе див двигается вместе с картой и пробивается исходный цвет
coloredDiv.style.position = 'absolute';
coloredDiv.style.top = '-2500px';
coloredDiv.style.left = '-2500px';
coloredDiv.style.width = '5000px';
coloredDiv.style.height = '5000px';
// z-index должен быть больше чем у карты, чтобы не пробивался исходный цвет
// у яндекса он динамичный и может меняться по добавлению новых элементов на карту
// поэтому ставим достаточно большое значение
coloredDiv.style.zIndex = '9999';
if (mapModeAttr === 'bw_light') {
var cloneLight = coloredDiv.cloneNode();
cloneLight.style['mixBlendMode'] = 'color';
cloneLight.style.zIndex = '9998';
cloneLight.style.opacity = '.5';
groundPaneElement && groundPaneElement.appendChild(cloneLight);
}
if (mapModeAttr === 'bw_dark') {
var cloneDark = coloredDiv.cloneNode();
cloneDark.style['mixBlendMode'] = 'soft-light';
cloneDark.style.zIndex = '9998';
cloneDark.style.opacity = '.85';
groundPaneElement && groundPaneElement.appendChild(cloneDark);
}
if (groundPaneElement) {
groundPaneElement.appendChild(coloredDiv);
}
}
}
var zoom = parseInt(mapZoomAttr, 10);
if (arMarkers.length > 1) {
map.setBounds(collection.getBounds(), {
checkZoomRange: true
}).then(function () {
if (zoom > 0 && (map.getZoom() == 0 || map.getZoom() > zoom)) {
map.setZoom(zoom);
}
});
if (zoom > 0 && (map.getZoom() == 0 || map.getZoom() > zoom)) {
map.setZoom(zoom);
}
} else if (zoom > 0 && (map.getZoom() == 0 || map.getZoom() > zoom)) {
map.setZoom(zoom);
}
map.events.add('sizechange', function () {
map.container.fitToViewport();
if (arMarkers.length > 1) {
map.setBounds(collection.getBounds(), {
checkZoomRange: true
}).then(function () {
if (zoom > 0 && (map.getZoom() == 0 || map.getZoom() > zoom)) {
map.setZoom(zoom);
}
});
} else if (zoom > 0 && (map.getZoom() == 0 || map.getZoom() > zoom)) {
map.setZoom(zoom);
}
});
});
}
function t_map_hexToHsl(H) {
// Convert hex to RGB first
var r = 0, g = 0, b = 0;
if (H.length === 4) {
r = '0x' + H[1] + H[1];
g = '0x' + H[2] + H[2];
b = '0x' + H[3] + H[3];
} else if (H.length === 7) {
r = '0x' + H[1] + H[2];
g = '0x' + H[3] + H[4];
b = '0x' + H[5] + H[6];
}
// Then to HSL
r /= 255;
g /= 255;
b /= 255;
var cmin = Math.min(r,g,b),
cmax = Math.max(r,g,b),
delta = cmax - cmin,
h = 0,
s = 0,
l = 0;
if (delta === 0)
h = 0;
else if (cmax === r)
h = ((g - b) / delta) % 6;
else if (cmax === g)
h = (b - r) / delta + 2;
else
h = (r - g) / delta + 4;
h = Math.round(h * 60);
if (h < 0)
h += 360;
l = (cmax + cmin) / 2;
s = delta === 0 ? 0 : delta / (1 - Math.abs(2 * l - 1));
s = +(s * 100).toFixed(1);
l = +(l * 100).toFixed(1);
return [h, s, l];
}