如何将 Leaflet 地图嵌入到 Reveal.js 演示文稿中?

2022-01-12 00:00:00 leaflet javascript css reveal.js

我正在尝试创建一个在 Reveal.js 之上运行的演示文稿,该演示文稿将在其中一张幻灯片中包含一个 Leaflet.js 地图.我已经包含了所有必要的 Javascript &CSS 文件到我的 Reveal.js 演示文稿中,我可以使地图出现在幻灯片上.

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.

Javascript 控制台中没有错误消息,并且浏览器似乎正在按照应有的方式从服务器下载地图图块.我相信这个问题与 Leaflet 地图图块的 CSS 代码有关 - .leaflet-tile 在 leaflet.css 中 - 在某种程度上与 Reveal.js 不兼容.

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?

<div id="map"> 我有以下 CSS:

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

一个明显的解决方法是使用 <iframe> 标签将地图嵌入到演示文稿中.似乎工作得很好,也许将框架分开会更好.然而,不利的一面是,如果演示文稿中有多个地图,每个地图都在其自己的 <iframe> 中,则 Leaflet.js 的副本会为每个 iframe 加载到内存中.

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.

编辑 #2: 一个更好的解决方案似乎是使用 PolymapsLeaflet.js.似乎可以将多个 Polymaps 地图嵌入到 reveal.js 演示文稿中.没有问题.

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.

推荐答案

我发现用 web 组件很容易做到,这样,shadow dom 将保护我的传单地图免受揭示 css 的邪恶之手

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

这是一个带有示例的仓库

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

这是网页组件

<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>

相关文章