Хобрук: Ваш путь к мастерству в программировании

Изогнутая линия между двумя ближайшими точками на картах Google

Можно нарисовать кривую линию (например, геодезическую линию) между двумя ближайшими точками на картах Google, например, с такими координатами:

p1 = (23.634501, -102.552783)

p2 = (17.987557, -92.929147)

Есть ли библиотека javascript для этого? и возможно ли контролировать кривизну линии?

Спасибо.

02.12.2013

  • Этот вопрос, кажется, имеет отношение к вашему - заголовок stackoverflow.com/questions/13433648/. 02.12.2013
  • Спасибо, но я знаю, что geodesic:true делает геодезические линии, но это не работает, когда расстояние между двумя точками ближе, и я хочу знать, есть ли другой способ сделать это. 02.12.2013
  • Теперь в полилинии Карт Google есть собственная логическая геодезическая опция, которая делает это автоматически: developers.google.com/maps/documentation/javascript/reference/ 13.08.2019

Ответы:


1

Вот библиотеки, которые я нашел

http://curved_lines.overfx.net/ Неработающая ссылка

http://www.geocodezip.com/v3_polyline_example_rhumb.html

http://www.geocodezip.com/v3_polyline_example_arc.html

На самом деле я только что обнаружил, что карта Google Polyline принимает список точек для построения. Таким образом, вы можете передать несколько точек, чтобы линия выглядела изогнутой.

PS: вы можете использовать функцию рисования дуги по двум ссылкам ниже, чтобы получить список точек для рисования.

07.03.2014

2

Совсем недавно я придумал другое решение, в котором не нужны полилинии, а вместо этого используется значение пути для значков маркеров, которое можно вычислить на лету.

В двух словах: вы просто создаете строку пути SVG для квадратичной кривой Безье от 0 до p2 — p1 и прикрепляете ее в качестве значка маркера к p1.

Длинная версия: координаты пикселей внутри контейнера можно получить, вызвав google.maps.Projection.fromLatLngToContainerPixel(). Строка для квадратичной кривой Безье выглядит так:

M [startX] [startY] q [controlX] [controlY] [endX] [endY]

Мы выберем (0,0) в качестве начальной точки, так как позже маркер будет размещен в этой точке. Относительное положение p2 теперь равно e = (p2.x - p1.x, p2.y - p1.y), а относительное положение точки на полпути между ними равно m = (e.x/2, e.y/2). Ортогональный вектор к e равен o = s * norm(-e.x / e.y, 1), где s — некоторый коэффициент масштабирования, а s = |e|/4 — хорошая отправная точка. Теперь у нас есть контрольная точка с c = (m.x + o.x, m.y + o.y) и путь:

path = „M 0 0 q c.x c.y e.x e.y“

Теперь, когда у нас есть этот путь, мы можем просто объявить значок:

var icon = {
    path : path,
    fillOpacity : 0,//important
    scale : 1,
    strokeOpacity: //yours,
    strokeColor : //yours,
    strokeWeight : //yours,
    clickable : false //important
};

Установка clickable в false необходима, потому что в противном случае область, заключенная в кривую, станет кликабельной, а основная карта не будет получать события мыши. Теперь мы можем добавить на карту маркер со значком пути в качестве параметра и позицией точки p1:

var marker = new google.maps.Marker({
    position : p1,
    icon : icon,
    map : map,
    clickable : false,
    zIndex : -100 //make the line appear behind ‚real’ markers
});

Несколько замечаний:

  • знак масштабного коэффициента ортогонала o определяет «направление» дуги («выше» или «ниже» e)
  • При изменении уровня масштабирования необходимо настроить масштаб значков следующим образом: marker.icon.scale = 1 / 2^(initialZoom - currentZoom) нет необходимости пересчитывать путь.

Образец:

Пример кривых Безье на картах Google

jsfiddle с жестко запрограммированным примером с использованием исходных пунктов вопроса

соответствующий код:

var p1 = new google.maps.LatLng(23.634501, -102.552783);
var p2 = new google.maps.LatLng(17.987557, -92.929147);

var markerP1 = new google.maps.Marker({
    position: p1,
    map: map
});
var markerP2 = new google.maps.Marker({
    position: p2,
    map: map
});
google.maps.event.addListener(map, 'projection_changed', function () {
    var p1 = map.getProjection().fromLatLngToPoint(markerP1.getPosition());
    var p2 = map.getProjection().fromLatLngToPoint(markerP2.getPosition());
    var e = new google.maps.Point(p1.x - p2.x, p1.y - p2.y);
    var m = new google.maps.Point(e.x / 2, e.y / 2);
    var o = new google.maps.Point(0, 7);
    var c = new google.maps.Point(m.x + o.x, m.y + o.y);
    var curveMarker2 = new google.maps.Marker({
        position: markerP1.getPosition(),
        icon: {
            path: "M 0 0 q " + c.x + " " + c.y + " " + e.x + " " + e.y,
            scale: 24,
            strokeWeight: 2,
            fillColor: '#009933',
            fillOpacity: 0,
            rotation: 180,
            anchor: new google.maps.Point(0, 0)
        }
    });
    curveMarker2.setMap(map);
    google.maps.event.addListener(map, 'zoom_changed', function () {
        var zoom = map.getZoom();
        var scale = 1 / (Math.pow(2, -zoom));
        var icon = {
            path: "M 0 0 q " + c.x + " " + c.y + " " + e.x + " " + e.y,
            scale: scale,
            strokeWeight: 2,
            fillColor: '#009933',
            fillOpacity: 0,
            rotation: 180,
            anchor: new google.maps.Point(0, 0)
        };
        curveMarker2.setIcon(icon);
    });
});
04.07.2014
  • поиграйте с жестко запрограммированным примером 04.02.2015
  • добавил соответствующий код к этому ответу, а также ссылку на рабочий jsfiddle с исходными точками. 04.02.2015
  • Вот обновленная скрипта, которая вычисляет ортогональные (в текущем примере она жестко запрограммирована). Он также имеет перетаскиваемые маркеры, поэтому вы можете протестировать его с различными точками и масштабами. 26.04.2015
  • Я пытаюсь понять, как заставить это работать с массивом конечных точек. Где P1 — это пункт отправления, а P2 и P3 — два отдельных (не соединенных) пункта назначения. Любые предложения, как я могу это сделать? 15.05.2015
  • Как ты смог добавить эту стрелку посередине. Я получаю изогнутые линии, но я не могу придумать способ получить стрелку в центре линии. 09.05.2019
  • Теперь в полилинии Карт Google есть логическая геодезическая опция, которая делает это автоматически: developers.google.com/maps/documentation/javascript/reference/ 13.08.2019
  • Это потрясающе. Мне было интересно (не пытаясь найти дыры), есть ли способ сделать путь плавным при масштабировании, а не внезапным прыжком - например, есть ли сценарий типа onupdatingzoom? 22.09.2019
  • Новые материалы

    Основы принципов S.O.L.I.D, Javascript, Git и NoSQL
    каковы принципы S.O.L.I.D? Принципы SOLID призваны помочь разработчикам создавать надежные, удобные в сопровождении приложения. мы видим пять ключевых принципов. Принципы SOLID были разработаны..

    Как настроить Selenium в проекте Angular
    Угловой | Селен Как настроить Selenium в проекте Angular Держите свое приложение Angular и тесты Selenium в одной рабочей области и запускайте их с помощью Mocha. В этой статье мы..

    Аргументы прогрессивного улучшения почти всегда упускают суть
    В наши дни в кругах веб-разработчиков много болтают о Progressive Enhancement — PE, но на самом деле почти все аргументы с обеих сторон упускают самую фундаментальную причину, по которой PE..

    Введение в Джанго Фреймворк
    Схема «работать умно, а не усердно» В этой и последующих статьях я познакомлю вас с тем, что такое фреймворк Django и как создать свое первое приложение с помощью простых и понятных шагов, а..

    Настольный ПК как «одно кольцо, чтобы править всеми» домашних компьютеров
    Вид после 9 месяцев использования С настольных компьютеров все началось, но в какой-то момент они стали «серверами», и мы все перешли на ноутбуки. В прошлом году я столкнулся с идеей настольных..

    Расширенные методы безопасности для VueJS: реализация аутентификации без пароля
    Руководство, которое поможет вам создавать безопасные приложения в долгосрочной перспективе Безопасность приложений часто упускается из виду в процессе разработки, потому что основная..

    стройный-i18следующий
    Представляем стройную оболочку для i18next. Эта библиотека, основанная на i18next, заключает экземпляр i18next в хранилище svelte и отслеживает события i18next, такие как languageChanged,..