编辑:好的,所以旧的解决方案工作得很好,但它需要直接从Leaflet Offline包下载文件,并修改它们,这并不理想。我现在已经成功地将 Leaflet Offline 包与 npm 和 React 一起使用。我建议首先阅读下面发布的旧解决方案,因为新解决方案是在此基础上构建的。这就是我所做的:
更新的新解决方案:
1 - 离线安装 Leaflet:npm install leaflet.offline@next
2 - 使用以下命令将 Leaflet Offline 包导入到您的 React 组件中:
import L from "leaflet"; // Remember that this must also be imported
import "leaflet.offline";
3 - 现在看看旧解决方案中的步骤 6。我们现在分别使用 L.tileLayer.offline 和 L.control.savetiles,而不是使用“generateOfflineTilelayer”和“generateControlSavetiles”。如果您像我一样使用 TypeScript,请在代码行上方添加 ts-ignore 作为注释,以防止由 TypeScript 引起的任何错误。因此,第 6 步中的 useEffect 代码现在如下所示:
useEffect(() => {
if(map){
// @ts-ignore
const tileLayerOffline = L.tileLayer.offline(
"https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png",
{
attribution: '© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors',
minZoom: 13,
}
);
tileLayerOffline.addTo(map);
// @ts-ignore
const controlSaveTiles = L.control.savetiles(
tileLayerOffline,
{
zoomlevels: [13, 14, 15, 16], // optional zoomlevels to save, default current zoomlevel
}
);
controlSaveTiles.addTo(map!);
}
}, [map]);
4 - 地图现在应该按预期工作。在尝试导入 leaflet.offline 时,我确实遇到了缺少声明文件的问题。对我来说,这个问题奇怪地只存在于我的一个组件中,而不存在于其他组件中。如果您遇到同样的问题,您可以尝试按照 IDE 的建议创建一个声明文件,或者您可以尝试在 import 语句的正上方添加“// @ts-ignore”。希望这对某人有帮助:)
旧解决方案:
好吧,所以我从来没有在网上找到任何人可以解决这个问题,但经过一些尝试和错误后,我已经解决了这个问题。我之所以希望能够在Leaflet中下载地图以供离线使用,是因为我正在使用Ionic、Capacitor和React制作一个手机应用程序。可能值得一提的是我也在使用打字稿。
为了其他人的利益,我将在下面发布有关如何实现此工作的指南。希望这能防止其他人经历我所经历的同样的挫折:D
所以我在使用 Leaflet.offline 插件时遇到的问题是 Leaflet.tileLayer.offline 或 Leaflet.control.saveTiles 无法被识别(可能是由于使用了 React)。以下是我为使离线地图正常工作而采取的步骤:
1 - 我最初是通过 npm 包使用 leaflet.offline 。我们想要更改插件,以便我们不再依赖插件对 Leaflet.tileLayer.offline 或 Leaflet.control.saveTiles 的使用。我们想要的是创建一些返回这两个提到的类的实例的方法,然后我们可以将这些方法导入到我们的 React 组件中。最简单的方法是不通过 npm 使用插件,而是直接下载插件的文件。因此,您应该做的第一件事是下载在插件的 GitHub 页面上找到的 leaflet.offline/src 文件夹内容的副本(https://github.com/allartk/leaflet.offline/tree/master/src)。您应该下载的文件是 ControlSaveTiles.js、TileLayerOffline.js 和 TileManager.js。
2 - 现在在您的 React 项目中创建一个文件夹。我将我的名称命名为 LeafletMapOfflinePlugin,但您可以将其命名为任何您想要的名称。然后将您下载的文件移动到该文件夹中。
3 - 打开 TileLayerOffline.js 文件,并将以下代码粘贴到文件底部。这将导出一个可用于创建 TileLayerOffline 类的新实例的函数,以便我们不再依赖 L.tileLayer.offline:
// Export a function that generates an offfline tilelayer-object,
// as the above expansion of L.tileLayer.offline doesn't work
export function generateOfflineTilelayer(url, options) {
return new TileLayerOffline(url, options)
}
4 - 打开 ControlSaveTiles.js 文件,并将以下代码粘贴到文件底部。这将导出一个可用于创建 ControlSaveTiles 类的新实例的函数,以便我们不再依赖 L.control.saveTiles:
// Export a function that generates a savetiles-object,
// as the above expansion of L.control.savetiles doesn't work
export function generateControlSavetiles(baseLayer, options) {
return new ControlSaveTiles(baseLayer, options);
}
5 - 现在可以使用以下导入将它们导入到任何 React 组件中:
import { generateOfflineTilelayer } from "<path-to-TileLayerOffline.js>";
import { generateControlSavetiles } from "<path-to-ControlSaveTiles.js>";
6 - 下面是如何在 React 组件(使用 TypeScript)中使用它的简单示例。这里我们使用useState存储MapContainer对象,并在useEffect中使用它来手动设置tileLayer和控件:
import L, { Map } from "leaflet";
import { MapContainer } from "react-leaflet";
import { generateOfflineTilelayer } from "<path-to-TileLayerOffline.js>";
import { generateControlSavetiles } from "<path-to-ControlSaveTiles.js>";
import React, { useState } from "react";
const LeafletMap: React.FC<LeafletMapProps> = () => {
const [map, setMap] = useState<Map | undefined>();
useEffect(() => {
if(map){
const tileLayerOffline = generateOfflineTilelayer(
"https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png",
{
attribution: '© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors',
minZoom: 13,
}
);
tileLayerOffline.addTo(map);
const controlSaveTiles = generateControlSavetiles(
tileLayerOffline,
{
zoomlevels: [13, 14, 15, 16], // optional zoomlevels to save, default current zoomlevel
}
);
controlSaveTiles.addTo(map!);
}
}, [map]);
return(
<MapContainer
style={{ width: "100vw", height: "20vh" }}
center={[63.446827, 10.421906]}
zoom={13}
scrollWheelZoom={false}
whenCreated={setMap}
>
</MapContainer>
)
}
7 - 您现在应该有一个带有控制元素的简单 Leaflet-map,当“+”(不要与用于缩放的“+”混淆。“+”是 leaflet.offline 的控制元素的默认值时,并且可以通过查看 leaflet.offline 的文档进行更改)单击后,它会下载并保存地图上当前可见区域的地图图块。如果需要,您可以转到网络浏览器的网络选项卡来检查这些图块的下载。单击“-”(再次强调,不要与缩放按钮混淆)时,所有下载的图块都会被删除。请参见下图,了解使用 leaflet.offline 的 ControlSaveTiles 时地图的外观;用于保存图块的控制元素位于用于缩放的控制元素下方:
![Leaflet offline map example](https://i.stack.imgur.com/FjYVZ.png)
好了,差不多就这样结束了。希望这对某人有帮助:D 还有与传单地图相关的提示;如果您在仅显示地图的一小部分时遇到问题,请尝试使用map.invalidateSize()(如果您的地图容器存储为“地图”)。这将重置并更新传单地图已知的设备宽度,这有望使地图正确渲染:D