Rails - перекрывающиеся карты Openlayers - PullRequest
0 голосов
/ 01 августа 2020

Я просто экспериментирую с картами Openlayers на своем сайте. Функциональность карты работает отлично, однако я не могу правильно расположить карты на моей странице.

Мне нужны карты, которые будут отображаться на моем экране результатов поиска: 1 карта на результат. Приведенный ниже код предназначен только для отображения карты basi c bootstrap для каждого результата. Это отображается нормально (например, карта для каждого результата, одна поверх другой, как показано на скриншоте ниже), пока я не добавлю код карты. При введении кода карты все перекрывается, как показано на втором снимке экрана.

Есть идеи? Спасибо!

Скриншот результатов без кода карты

Скриншот результатов с кодом карты

      <% @locations.each do |location| %>
        
            <div class="card" style="width: 18rem;">
                  <div id="map" class="map">
                  <script type="text/javascript">
                    var map = new ol.Map({
                      target: 'map',
                      layers: [
                        new ol.layer.Tile({
                          source: new ol.source.OSM()
                        })
                      ],
                          view: new ol.View({
                            center: ol.proj.fromLonLat([-0.479642,52.641882]),
                            zoom: 10
                          })
                    });
                  </script>
                  
              <div class="card-body">
                <h5 class="card-title">Card title</h5>
                <p class="card-text">Some quick example text to build on the card title and make up the bulk of the card's content.</p>
                <a href="#" class="btn btn-primary">Go somewhere</a>
              </div>
            </div>

            </br></br>
      <% end %>

1 Ответ

0 голосов
/ 02 августа 2020

Этот взгляд - чистые спагетти. Вам не хватает двух закрывающих тегов </div>, и вы создаете несколько элементов с одним и тем же атрибутом ID, который дает недопустимый документ и вызывает синтаксический анализ в нестандартном режиме. Мой совет - начать использовать валидатор HTML и разделять контент, поведение и представление, что значительно упрощает написание качественного кода.

Когда у вас есть несколько элементов с одним и тем же атрибутом id document.getElementById и document.querySelector обычно возвращает первый элемент в DOM, но я не верю, что это на самом деле стандартизовано, поскольку это запрещено в первую очередь, и результаты могут отличаться в разных браузерах.

<% @locations.each do |location| %>
  <div class="card">
    <div class="map"></div>
    <div class="card-body">
      <h5 class="card-title">Card title</h5>
      <p class="card-text">Some quick example text to build on the card title and make up the bulk of the card's content.</p>
      <a href="#" class="btn btn-primary">Go somewhere</a>
    </div>
  </div>
<% end %>

При использовании OpenLayers (или Google Maps или Leaflet) вам на самом деле не нужно использовать идентификаторы для элемента целевой карты - это просто сделано для создания простых примеров быстрого запуска, которые на самом деле не являются отличной отправной точкой, если вы хотите добавить несколько карт на страницу, поскольку вам нужно без нужды перепрыгивать через кучу обручей, просто чтобы назначить уникальные идентификаторы, а затем передать их в свой JavaScript. Вместо этого вы можете просто передать любой объект HTMLElement .

Теперь давайте напишем немного настоящего взрослого JavaScript:

// place this in your packs (Rails 6) or assets pipeline (older versions) 
// use 'DOMContentLoaded' if you are not using turbolinks
document.addEventListener('turbolinks:load', function(){
  let elements = document.querySelectorAll('.card .map');
  let maps = elements.forEach(function(element){
    new ol.Map({
      target: element,
      layers: [
        new ol.layer.Tile({
          source: new ol.source.OSM()
        })
      ],
      view: new ol.View({
        center: ol.proj.fromLonLat([-0.479642,52.641882]),
        zoom: 10
      })
    });
  });
});

Это не ракетостроение. Мы выбираем элементы, когда turbolinks выполняет замену своей страницы magi c (и при начальной загрузке страницы), а затем инициализируем экземпляр карты для каждого элемента, который соответствует селектору. И вы не отправляете точно такое же JavaScript n количество раз для каждой итерации l oop, как с этой мерзостью тега скрипта.

Используйте атрибуты данных , если вы хотите передавать такие данные, как позиции маркеров, между Rails и JavaScript.

<% @locations.each do |location| %>
  <div class="card">
     <%= content_tag :div,
         class: 'map',
         data: {
           lat: location.latitude,
           lon: location.longitude
         }
     %> 
     <div class="card-body">
       <h5 class="card-title">Card title</h5>
       <p class="card-text">Some quick example text to build on the card title and make up the bulk of the card's content.</p>
       <a href="#" class="btn btn-primary">Go somewhere</a>
    </div>
  </div>
<% end %>
document.addEventListener('turbolinks:load', function(){
  let elements = document.querySelectorAll('.card .map');
  let maps = elements.forEach(function(element){
    new ol.Map({
      target: element,
      layers: [
        new ol.layer.Tile({
          source: new ol.source.OSM()
        })
      ],
      view: new ol.View({
        // Map now centers on right location. Magic!
        center: ol.proj.fromLonLat([data.lon, data.lat]),
        zoom: 10
      })
    });
  });
});
...