Изменение позиции всплывающего окна на маркере Leaflet?

13

Я хочу открыть всплывающее окно в нижней части моего значка маркера в Leaflet.

мой код:

var mymap = L.map('mapid').setView([51.505, -0.09], 13);

L.tileLayer('https://api.tiles.mapbox.com/v4/{id}/{z}/{x}/{y}.png?access_token=pk.eyJ1IjoibWFwYm94IiwiYSI6ImNpandmbXliNDBjZWd2M2x6bDk3c2ZtOTkifQ._QA7i5Mpkd_m30IGElHziw', {
    maxZoom: 18,
    attribution: 'Map data &copy; <a href="http://openstreetmap.org">OpenStreetMap</a> contributors, ' +
    '<a href="http://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>, ' +
    'Imagery © <a href="http://mapbox.com">Mapbox</a>',
    id: 'mapbox.streets'
}).addTo(mymap);

var lati = 51.51;
var longi = -0.09;

var popupLocation1 = new L.LatLng(lati, longi);
var popupContent1 = 'This is a nice popup';

popup1 = new L.Popup();
popup1.setLatLng(popupLocation1);
popup1.setContent(popupContent1);

var m1 = L.marker([ lati, longi ]).addTo(mymap);

m1.bindPopup(popup1);

m1.openPopup();

Так что я получаю всплывающее окно поверх моего маркера.

Я хочу получить всплывающее окно внизу, как:

введите описание изображения здесь

Герд
источник
Проверьте это Q / A, stackoverflow.com/questions/27144334/…
artwork21
по вашей ссылке нет рабочего решения. Возможно, комментарий правдив: «что вы могли бы сделать, это нажать на маркер и нарисовать свое собственное всплывающее окно с пользовательским кодом» Нет простого способа для нижнего всплывающего окна?
Герд
1
Текущая ситуация такая же, как в ссылке на комментарий artwork21, относительно вашего вопроса для всплывающего окна под маркером. Смотрите ответ FranceImage ( stackoverflow.com/a/27144900/5108796 ) с предлагаемым плагином. Вы можете использовать этот плагин или получить от него вдохновение для создания своего собственного всплывающего окна.
ghybs
Разве мы не можем сделать это в CSS-позиционировании самого всплывающего окна? Потому что по умолчанию это ссылка снизу, если мы переключимся на верх, тогда это будет правильно [с фиксированным смещением] независимо от выбранных шрифтов / размеров шрифта / высоты строк и количества строк текста? Я, наверное, что-то упускаю.
user3445853

Ответы:

4

Вы можете указать смещения с помощью popupAnchorпараметров, но не там, где вы ожидаете этого. Во-первых, вам нужно указать значок:

var myIcon = L.divIcon({ popupAnchor: [0, -30] });

Затем вы можете использовать этот значок в опциях вашего маркера:

var marker = L.marker(location, {
                 icon: myIcon
             }).bindPopup(function (marker) {...}); //Shortened

Теперь ваше всплывающее окно открывается на 30 пикселей выше маркера. Это не совсем то, о чем вы просили, так как вам также нужно поместить маленький стрелочный треугольник в верхней части вашего всплывающего окна, но я думаю, что все же стоит упомянуть.

Alex
источник
Та же проблема, что и в более недавнем ответе [29 августа 2019] @Johannes: это смещение неверно, так как во всплывающем окне есть вторая или дополнительная строка текста; или изменения в CSS (размер шрифта, шрифт, высота строки, отступы, поля, размер всплывающего окна, ...). Следовательно, первоначальный ответ «нет родного решения» остается в силе.
user3445853
2

Я знаю, что это старый вопрос, но вам не нужно брать объезд @Robert, описанный в его ответе.

Как Popupнаследуется от DivOverlay, вы можете установить опцию смещения непосредственно при инициализации Popup:

    var popup = L.popup({
        offset: [0, -30]
    })
      .setLatLng(location)
      .setContent("Test Text")
      .openOn(mapId);

Прочитайте документы: https://leafletjs.com/reference-1.5.0.html#popup

Johannes
источник
Проблема с этим подходом состоит в том, что у вас есть магические числа для смещения: если размер шрифта или шрифт или даже высота строки изменяется, смещение плохое. Еще более проблематично, если некоторые всплывающие окна содержат вторую (или третью и т. Д.) Строку текста, теперь они имеют полную высоту строки (или две и т. Д.) Слишком высоко и, вероятно, полностью перекрывают маркер и его окрестность. Вам, вероятно, потребуется измерить высоту текста внутри всплывающего окна, динамически изменить смещение и переместить его с помощью JS во время / после рендеринга; или иметь очень фиксированный CSS и вычислить его во время листовки перед добавлением маркера.
user3445853
1

Это кажется возможным только в CSS. Ниже я переопределяю (с !important) только три элемента CSS и добавляю один :beforeпсевдоэлемент. По сути, я сначала выстраиваю всплывающее окно с верхом, а не с низом , где все 55px зависит от выбранного вами маркера и личного вкуса.

Затем я перемещаю «подсказку» всплывающего окна аналогичным образом снизу вверх top:0pxи обнаруживаю, что это сделано не с помощью «обычного» трюка (то есть: сначала поместите на краю пузыря псевдоэлемент размером 0x0 с толстой прозрачной рамкой, затем раскрасьте, чтобы противоположная граница элемента, на которую вы хотите указать; в нашем случае это нижняя граница). Вместо этого он, кажется, сделан из прямоугольника, повернутого откуда-то сверху слева (может быть: потому что он заставляет браузер использовать графический процессор и, следовательно, ускоряет все?), И я недостаточно хорошо понимаю точку (извините за каламбур) ( мой совет в нужном месте, но невидимый); так что я просто убираю тень с ящика, которая сейчас находится не в том месте, и оставляю все как есть - любому, кто понимает «старый совет», пожалуйста, настройте его.

Поэтому вместо этого я делаю свой собственный совет с «нормальным» процессом (если вы не уверены, измените четыре цвета рамки ниже, вместо 3x прозрачного и 1x белого - например border-bottom-color: blue; border-left-color: green; border-top-color: yellow' border-right-color: red).

#map {
   position: absolute;
   top: 0;
   right: 0;
   left: 0;
   bottom: 0;
   z-index: 0;
}
.leaflet-popup {top: 55px !important;}
/* Here I move the "tip" to the right location, but didn't succeed in making it visible. So I just remove the box-shadow and leave it: */
.leaflet-popup-tip-container {
   top: 0px !important;
}
.leaflet-popup-tip {
   box-shadow: none !important;
}
.leaflet-popup:before 
    {
    content: "";
    position: absolute;
    border: 13px solid transparent;
    border-bottom-color: white;
    bottom: 0px;
    margin-left: -13px;
}

Как показывает этот JSFiddle , нет проблем с разными размерами всплывающих окон (разной ширины, разной высоты текста), если вы попробуете оба маркера.

В целом это кажется устойчивым к обновлениям в Leaflet, поскольку элементы, которые я переопределяю, вряд ли изменятся.

user3445853
источник