How to embed a Leaflet map into a Reveal.js presentation?

↘锁芯ラ 提交于 2019-12-02 00:44:07

问题


I am trying to create a presentation running on top of Reveal.js, which would include a Leaflet.js map within one of the slides. I have included all necessary Javascript & CSS files into my Reveal.js presentation and I can make the map appear on the slide.

However, the problem is: map tiles are not displayed correctly. Instead of the actual map tiles, all I am seeing is gray background and some horizontal black lines. I can zoom in/out and pan the map, and the black lines are moving accordingly.

There are no error message in the Javascript console, and the browser seems to be downloading map tiles from server exactly as it should. I believe the problem has something to do with the CSS code of Leaflet map tiles - .leaflet-tile within leaflet.css - being somehow incompatible with Reveal.js.

The question is: Does anyone know how to get around this issue? Or is it a deadend with no possible solution?

I have the following CSS for the <div id="map">:

#map {
    height:400px;
    width:100%;
}

EDIT: One obvious workaround for this is to use <iframe> tag to embed the map into the presentation. Seems to work just fine, and maybe it is better to keep the frameworks separated. However, the downside is that if there are several maps in the presentation, each within its own <iframe>, a copy of Leaflet.js is loaded to memory for each and every iframe.

EDIT #2: A better solution, it seems, is to use Polymaps instead of Leaflet.js. It seems that several Polymaps maps can be embedded into a reveal.js presentaion. No issues.


回答1:


It might be happening because the #map element is hidden (due to the hidden slide) when it is initialized, so it cannot read the dimensions..

Try using map.invalidateSize(false); once your slide becomes visible..

Reveal.addEventListener( 'slidechanged', function( event ) {
    // event.previousSlide, event.currentSlide, event.indexh, event.indexv
    if (event.indexh == 5){ // assuming your 5th slide is the one with the map
        map.invalidateSize(false); // assuming that map holds the the reference to your leaflet instance
    }
} );



回答2:


I found it easily to do it with a web component, this way, the shadow dom will protect my leaflet map from the evil hands of reveals css

here is a repo with an example

<link rel="import" href="./leaflet-map.html">
...
<div class="reveal">
  <div class="slides">
    <section data-state="map">
       <leaflet-map></leaflet-map>
    </section>
  </div>
</div>

Here is the web component

<template id="leaflet-map-template">
<link rel="stylesheet" href="./bower_components/leaflet/dist/leaflet.css">
<div id="mapid" style="height: 500px"></div>
    <!-- LEAFLET JS -->
</template>
<script src="./bower_components/leaflet/dist/leaflet.js"></script>
<script>
    class LeafletMap extends HTMLElement {
        constructor () {
            super();
            let tmpl = document.currentScript.ownerDocument.querySelector('template')
            let shadowRoot = this.attachShadow({mode: 'open'})
            shadowRoot.appendChild(tmpl.content.cloneNode(true))

            let mapDiv = this.shadowRoot.getElementById('mapid')
            this.map = L.map(mapDiv).setView([19.39682052576622, -99.13478851318361], 13)
            // this.setAttribute('map', map)
            // Tiles de open street maps
            //L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png").addTo(map)

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

                iconSize:     [40, 40], // size of the icon
                iconAnchor:   [20, 20], // point of the icon which will correspond to marker's location
                tooltipAnchor: [20,0]
            })
            L.marker(
                [19.418657758792698, -99.14065182209016],
                {icon: myIcon}
            ).bindTooltip('Ranchito').addTo(this.map)
        }

        resize() {
            this.map.invalidateSize()
        }
    }
    window.customElements.define('leaflet-map', LeafletMap)
</script>


来源:https://stackoverflow.com/questions/20119488/how-to-embed-a-leaflet-map-into-a-reveal-js-presentation

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!