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

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

p1 = (23.634501, -102.552783)

p2 = (17.987557, -92.929147)

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

Спасибо.

Ответ 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: u может использовать функцию дуги дуги в двух ссылках ниже, чтобы получить список точек для рисования

Ответ 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) нет необходимости пересчитывать путь.

Пример:

Sample of bezier curves on google maps

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);
    });
});