1/** 2 * ÐаÑÑÑ ÑайÑа без ÑекламÑ: Ð·Ð¾Ð½Ñ Ð´Ð¾ÑÑавки и меÑка оÑиÑа на ÑвоÑм клÑÑе JS API ЯндекÑа. 3 * 4 * ÐаÑем. РанÑÑе каÑÑÑ Ð²ÑÑавлÑлиÑÑ Ð²Ð¸Ð´Ð¶ÐµÑом «ÐонÑÑÑÑкÑоÑа каÑÑ» 5 * (`api-maps.yandex.ru/services/constructor/1.0/js/?um=â¦`), и оÑенÑÑ 2026 Ð¯Ð½Ð´ÐµÐºÑ Ð½Ð°Ñал 6 * показÑваÑÑ Ð² нÑм ÑекламÑ. ÐÑклÑÑиÑÑ ÐµÑ Ð¿Ð°ÑамеÑÑом нелÑзÑ, API-клÑÑ Ð½Ð° Ð½ÐµÑ Ð½Ðµ влиÑÐµÑ â 7 * он лиÑÑ Ð´Ð¾Ð±Ð°Ð²Ð»ÑÐµÑ Ð¿Ð¾Ð¸Ñк, маÑÑÑÑÑÑ Ð¸ паноÑамÑ. Ð JS API ÑÐµÐºÐ»Ð°Ð¼Ñ Ð½ÐµÑ, поÑÑÐ¾Ð¼Ñ ÐºÐ°ÑÑа 8 * ÑиÑÑеÑÑÑ Ð·Ð´ÐµÑÑ ÑамоÑÑоÑÑелÑно. 9 * 10 * ÐÐ¾Ð½Ñ Ð±ÐµÑÑÑÑÑ Ð¸Ð· ÑÐµÑ Ð¶Ðµ Ñайлов, по коÑоÑÑм ÑÑиÑаеÑÑÑ Ð´Ð¾ÑÑавка 11 * (`sc-modules/yamaps-calculate/delimaps_<гоÑод>.geojson`), â каÑÑа и ÑаÑÑÑÑ Ð±Ð¾Ð»ÑÑе 12 * не могÑÑ ÑазойÑиÑÑ: попÑавили Ð·Ð¾Ð½Ñ Ð² geojson, изменилаÑÑ Ð¸ каÑÑинка. 13 * 14 * Ðак вÑÑавлÑÑÑ Ð½Ð° ÑÑÑаниÑÑ (годиÑÑÑ Ð¸ в Ñаблоне, и в ÑекÑÑе ÑÑÑаниÑÑ Ð¸Ð· админки): 15 * 16 * <div class="vv-map" data-zones="spb" style="height:450px"></div> 17 * <div class="vv-map" data-point="59.888848,30.482479" data-label="ÐнÑк и ÐнÑÑка оÑиÑ"></div> 18 * 19 * ÐоÑода зон: spb, msk, nsk, rnd. ÐаÑÑа гÑÑзиÑÑÑ Ð»ÐµÐ½Ð¸Ð²Ð¾ â API ЯндекÑа подÑÑгиваеÑÑÑ, 20 * ÑолÑко когда каÑÑа подÑÐµÐ·Ð¶Ð°ÐµÑ Ðº ÑкÑанÑ, и ÑолÑко еÑли каÑÑа на ÑÑÑаниÑе еÑÑÑ. 21 */ 22(function () { 23 'use strict'; 24 25 // ÑÐ¾Ñ Ð¶Ðµ клÑÑ, ÑÑо Ñ ÑаÑÑÑÑа доÑÑавки: sc-modules/yamaps-calculate/yandex_api_keys.php 26 var API_KEY = 'cfa00a0f-9b09-4dda-a177-3899d03ad061'; 27 var ZONES_URL = '/sc-modules/yamaps-calculate/delimaps_{city}.geojson'; 28 29 // ÐаÑколÑко пÑиблизиÑÑ ÐºÐ°ÑÑÑ Ð¿ÑоÑив ÑаÑÑÑиÑанной по зонам: Ñ ÐеÑеÑбÑÑга и ÐоÑÐºÐ²Ñ 30 // Ð·Ð¾Ð½Ñ Ð·Ð°Ð½Ð¸Ð¼Ð°ÑÑ Ð¼ÐµÐ½ÑÑÑÑ ÑаÑÑÑ ÐºÐ°Ð´Ñа, поÑÑÐ¾Ð¼Ñ Ð½Ð° Ñаг кÑÑпнее. Ðожно задаÑÑ Ð¸ на меÑÑе 31 // аÑÑибÑÑом data-zoom-plus. 32 var ZOOM_PLUS = { spb: 1, msk: 1 }; 33 34 var apiPromise = null; 35 var zonesCache = {}; 36 37 /** ÐодклÑÑÐ°ÐµÑ JS API один Ñаз на ÑÑÑаниÑÑ */ 38 function loadApi() { 39 if (!apiPromise) { 40 apiPromise = new Promise(function (resolve, reject) { 41 var script = document.createElement('script'); 42 script.src = 'https://api-maps.yandex.ru/2.1/?apikey=' + API_KEY + '&lang=ru_RU'; 43 script.onload = function () { ymaps.ready(resolve); }; 44 script.onerror = reject; 45 document.head.appendChild(script); 46 }); 47 } 48 return apiPromise; 49 } 50 51 /** ÐÐ¾Ð½Ñ Ð³Ð¾Ñода; один запÑÐ¾Ñ Ð½Ð° гоÑод, даже еÑли каÑÑ Ð½Ð° ÑÑÑаниÑе неÑколÑко */ 52 function loadZones(city) { 53 if (!zonesCache[city]) { 54 zonesCache[city] = fetch(ZONES_URL.replace('{city}', city)).then(function (r) { 55 if (!r.ok) { 56 throw new Error('Ð·Ð¾Ð½Ñ ' + city + ': оÑÐ²ÐµÑ ' + r.status); 57 } 58 return r.json(); 59 }); 60 } 61 return zonesCache[city]; 62 } 63 64 /** ÐбÑие наÑÑÑойки каÑÑÑ: без лиÑÐ½Ð¸Ñ ÐºÐ½Ð¾Ð¿Ð¾Ðº и без пеÑÐµÑ Ð²Ð°Ñа пÑокÑÑÑки ÑÑÑаниÑÑ */ 65 function createMap(el, center, zoom) { 66 var map = new ymaps.Map(el, { 67 center: center, 68 zoom: zoom, 69 controls: ['zoomControl', 'fullscreenControl'] 70 }, { 71 suppressMapOpenBlock: true // без плаÑки «ÐÑкÑÑÑÑ Ð² Ð¯Ð½Ð´ÐµÐºÑ ÐаÑÑÐ°Ñ Â» 72 }); 73 map.behaviors.disable('scrollZoom'); 74 if (window.matchMedia && window.matchMedia('(max-width: 767px)').matches) { 75 map.behaviors.disable('drag'); // на ÑелеÑоне каÑÑа не должна ловиÑÑ Ð¿Ð°Ð»ÐµÑ Ð¿Ñи пÑокÑÑÑке 76 } 77 return map; 78 } 79 80 /** ÐÐ¾Ð»Ð¸Ð³Ð¾Ð½Ñ Ð·Ð¾Ð½ доÑÑавки: ÑвеÑа и подпиÑи беÑÑÑÑÑ Ð¸Ð· Ñамого geojson */ 81 function drawZones(el, city) { 82 return loadZones(city).then(function (data) { 83 var map = createMap(el, [59.93, 30.33], 9); 84 var zones = new ymaps.GeoObjectCollection(); 85
86 data.features.forEach(function (zone) { 87 // в geojson кооÑдинаÑÑ Ð¸Ð´ÑÑ [долгоÑа, ÑиÑоÑа], каÑÑе нÑжен обÑаÑнÑй поÑÑдок 88 var ring = zone.geometry.coordinates[0].map(function (c) { return [c[1], c[0]]; }); 89 var p = zone.properties || {}; 90 zones.add(new ymaps.Polygon([ring], {}, { 91 fillColor: p.fill || '#1bad03', 92 fillOpacity: typeof p['fill-opacity'] === 'number' ? p['fill-opacity'] : 0.3, 93 strokeColor: p.stroke || '#1bad03', 94 strokeWidth: parseInt(p['stroke-width'], 10) || 2, 95 strokeOpacity: typeof p['stroke-opacity'] === 'number' ? p['stroke-opacity'] : 0.9 96 })); 97 }); 98 99 map.geoObjects.add(zones); 100 101 var plus = el.hasAttribute('data-zoom-plus') 102 ? Number(el.getAttribute('data-zoom-plus')) 103 : (ZOOM_PLUS[city] || 0); 104 105 return map.setBounds(zones.getBounds(), { checkZoomRange: true, zoomMargin: 10 }) 106 .then(function () { 107 if (plus) { 108 map.setZoom(map.getZoom() + plus, { checkZoomRange: true }); 109 } 110 }); 111 }); 112 } 113 114 /** Ðдна меÑка Ñ Ð¿Ð¾Ð´Ð¿Ð¸ÑÑÑ â Ð´Ð»Ñ ÐºÐ°ÑÑÑ Â«Ð³Ð´Ðµ Ð¼Ñ Ð½Ð°Ñ Ð¾Ð´Ð¸Ð¼ÑÑ» */ 115 function drawPoint(el, coords, label) { 116 var map = createMap(el, coords, Number(el.getAttribute('data-zoom')) || 13); 117 map.geoObjects.add(new ymaps.Placemark(coords, { 118 iconCaption: label || '', 119 hintContent: label || '' 120 }, { 121 preset: 'islands#orangeFoodIcon' 122 })); 123 } 124 125 /** РиÑÑÐµÑ ÐºÐ¾Ð½ÐºÑеÑнÑÑ ÐºÐ°ÑÑÑ; оÑибки не Ð´Ð¾Ð»Ð¶Ð½Ñ ÑонÑÑÑ Ð¾ÑÑалÑнÑÑ ÑÑÑаниÑÑ */ 126 function render(el) { 127 if (el.dataset.vvMapReady) { 128 return; 129 } 130 el.dataset.vvMapReady = '1'; 131 132 loadApi().then(function () { 133 var zones = el.getAttribute('data-zones'); 134 if (zones) { 135 return drawZones(el, zones); 136 } 137 var point = (el.getAttribute('data-point') || '').split(',').map(Number); 138 if (point.length === 2 && point.every(function (n) { return !isNaN(n); })) { 139 drawPoint(el, point, el.getAttribute('data-label')); 140 } 141 }).catch(function (e) { 142 el.dataset.vvMapReady = ''; 143 if (window.console) { 144 console.warn('каÑÑа не поÑÑÑоена:', e); 145 } 146 }); 147 } 148 149 /** ÐÑÐµÑ ÐºÐ°ÑÑÑ Ð½Ð° ÑÑÑаниÑе и ÑиÑÑÐµÑ Ð¸Ñ Ð¿Ñи пÑиближении к ÑкÑÐ°Ð½Ñ */ 150 function init() { 151 var maps = document.querySelectorAll('.vv-map:not([data-vv-map-ready])'); 152 if (!maps.length) { 153 return; 154 } 155 if (!window.IntersectionObserver) { 156 Array.prototype.forEach.call(maps, render); 157 return; 158 } 159 var watcher = new IntersectionObserver(function (entries) { 160 entries.forEach(function (entry) { 161 if (entry.isIntersecting) { 162 watcher.unobserve(entry.target); 163 render(entry.target); 164 } 165 }); 166 }, { rootMargin: '300px' }); 167 Array.prototype.forEach.call(maps, function (el) { watcher.observe(el); }); 168 } 169 170 if (document.readyState === 'loading') { 171 document.addEventListener('DOMContentLoaded', init); 172 } else { 173 init(); 174 } 175 // каÑÑÑ Ð¼Ð¾Ð³ÑÑ Ð¿ÑиезжаÑÑ Ð²Ð¼ÐµÑÑе Ñ ÑодеÑжимÑм вÑплÑваÑÑÐ¸Ñ Ð¾ÐºÐ¾Ð½ 176 window.vvMapInit = init; 177})();
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.