Смени привычный вид из окна
на морской простор
7 ДНЕЙ
Длительность путешествия
150 МОРСКИХ МИЛЬ
Общее расстояние
27 °C
Средняя температура
2000 $
Стоимость за все
function init() { // Создаём карту и ставим начальный центр var map = L.map('yr-map').setView([36.752, 28.938], 9); // Подключаем OpenStreetMap тайлы L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { attribution: '© OpenStreetMap contributors' }).addTo(map); // Добавляем линии маршрута по дням days.forEach(function(day) { L.polyline(day.path, { color: '#1a7fb8', weight: 3 }).addTo(map) .bindPopup('' + day.weekday + '
' + day.desc); }); // Добавляем маркеры стоянок stops.forEach(function(stop) { L.marker(stop.ll).addTo(map).bindPopup(stop.name); }); } // Подложки по порядку: светлая CARTO → OpenStreetMap (обесцвеченная) → Esri светло-серая var TILES = [ { url: 'https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}{r}.png', o: { subdomains: 'abcd', attribution: '© OpenStreetMap © CARTO' } }, { url: 'https://tile.openstreetmap.org/{z}/{x}/{y}.png', o: { attribution: '© OpenStreetMap' }, gray: true }, { url: 'https://server.arcgisonline.com/ArcGIS/rest/services/Canvas/World_Light_Gray_Base/MapServer/tile/{z}/{y}/{x}', o: { attribution: '© Esri', maxZoom: 16 } } ]; function addTiles(map, i) { if (i >= TILES.length) return; var t = TILES[i], el = document.getElementById('yr-map'); el.classList.toggle('yr-osm', !!t.gray); var layer = L.tileLayer(t.url, L.extend({ maxZoom: 18 }, t.o)).addTo(map); var ok = false, errors = 0, switched = false; function next() { if (switched || ok) return; switched = true; map.removeLayer(layer); addTiles(map, i + 1); } layer.on('tileload', function () { ok = true; }); layer.on('tileerror', function () { if (++errors >= 3) next(); }); setTimeout(next, 3000); } function init() { var map = L.map('yr-map', { scrollWheelZoom: false, zoomControl: true }); addTiles(map, 0); // Бледная линия всего маршрута var all = []; days.forEach(function (d) { all = all.concat(d.path); }); L.polyline(all, { color: '#1a7fb8', weight: 2, opacity: .25, dashArray: '4 6' }).addTo(map); map.fitBounds(L.latLngBounds(all).pad(0.1)); // Маркеры стоянок var pins = stops.map(function (s, i) { var m = L.marker(s.ll, { icon: L.divIcon({ className: '', html: '
', iconSize: [14,14], iconAnchor: [7,7] }) }) .addTo(map) .bindTooltip(s.name, { permanent: true, direction: i === 1 ? 'right' : 'top', offset: i === 1 ? [8,0] : [0,-8], className: 'yr-label' }); return m; }); var done = L.polyline([], { color: '#1a7fb8', weight: 4, opacity: .95 }).addTo(map); var boat = L.marker(stops[0].ll, { icon: L.divIcon({ className: '', html: '
', iconSize: [30,30], iconAnchor: [15,15] }), zIndexOffset: 1000 }).addTo(map); // Длины отрезков для плавной интерполяции days.forEach(function (d) { d.cum = [0]; for (var i = 1; i < d.path.length; i++) { d.cum.push(d.cum[i-1] + map.distance(d.path[i-1], d.path[i])); } d.len = d.cum[d.cum.length-1]; }); function partial(d, f) { var target = d.len * f, pts = [d.path[0]]; for (var i = 1; i < d.path.length; i++) { if (d.cum[i] <= target) { pts.push(d.path[i]); continue; } var k = (target - d.cum[i-1]) / (d.cum[i] - d.cum[i-1]); var a = d.path[i-1], b = d.path[i]; pts.push([a[0] + (b[0]-a[0])*k, a[1] + (b[1]-a[1])*k]); break; } return pts; } var range = document.getElementById('yr-range'); var elDay = document.getElementById('yr-day'), elLeg = document.getElementById('yr-leg'), elDesc = document.getElementById('yr-desc'); var ticks = document.getElementById('yr-ticks'); // Подписи под ползунком ['Старт','1','2','3','4','5','6','7'].forEach(function (t, i) { var s = document.createElement('span'); s.textContent = i === 0 ? t : 'День ' + t; s.onclick = function () { range.value = i * 100; render(); }; ticks.appendChild(s); }); var lastDay = -1; function render() { var v = +range.value / 100; // 0..7 var di = Math.min(Math.floor(v), 6); // текущий день (0..6) var f = v - di; if (v >= 7) { di = 6; f = 1; } var pts = []; for (var i = 0; i < di; i++) pts = pts.concat(days[i].path); var cur = v > 0 ? partial(days[di], f) : [stops[0].ll]; pts = pts.concat(cur); done.setLatLngs(pts); boat.setLatLng(cur[cur.length-1]); // Подсветка пройденных стоянок stops.forEach(function (s, i) { var reached = i === 0 || days.some(function (d, k) { return d.to === i && (k < di || (k === di && f >= 1)); }); pins[i].getElement() && pins[i].getElement().firstChild.classList.toggle('dim', !reached); }); range.style.background = 'linear-gradient(to right,#1a7fb8 ' + (v/7*100) + '%,#c9d8e2 ' + (v/7*100) + '%)'; var shownDay = v === 0 ? -1 : (f === 0 && di > 0 ? di - 1 : di); if (v >= 7) shownDay = 6; Array.prototype.forEach.call(ticks.children, function (el, i) { el.classList.toggle('on', i === shownDay + 1); }); if (shownDay !== lastDay) { lastDay = shownDay; if (shownDay < 0) { elDay.textContent = 'Старт'; elLeg.textContent = 'Гёчек, марина D-Marin'; elDesc.textContent = 'Передвиньте ползунок, чтобы пройти маршрут день за днём.'; } else { var d = days[shownDay]; elDay.textContent = 'День ' + (shownDay + 1) + ' · ' + d.weekday + ' · ' + d.miles + ' миль'; elLeg.textContent = stops[d.from].name + ' → ' + stops[d.to].name; elDesc.textContent = d.desc; } } } range.addEventListener('input', render); render(); // Tilda иногда меняет размеры блока после загрузки — перерисовываем карту function fix() { map.invalidateSize(); map.fitBounds(L.latLngBounds(all).pad(0.1)); } setTimeout(fix, 300); window.addEventListener('load', fix); if (window.ResizeObserver) new ResizeObserver(function () { map.invalidateSize(); }).observe(document.getElementById('yr-map')); } loadLeaflet(0); })();