首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用leaflet.offline和React?

用leaflet.offline和React?
EN

Stack Overflow用户
提问于 2021-09-07 16:36:07
回答 1查看 1.5K关注 0票数 5

我正在开发一个React应用程序,我正在尝试实现一个传单地图,支持离线下载地图块。为此,我考虑使用leaflet.offline (https://github.com/allartk/leaflet.offline),但我不确定如何使用这个库进行React?

如何将leaflet.offline与React一起使用,或者是否有任何特定于React的库支持使用传单离线下载地图块?

谢谢你的帮助!

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-09-12 16:10:06

编辑:好的,所以旧的解决方案工作得很好,但是它需要直接从离线传单包下载文件,并修改它们,这并不理想。我现在已经成功地使用了小册子离线包与npm和React。我建议先阅读下面发布的旧解决方案,因为新的解决方案是在此基础上建立起来的。我所做的是:

更新的新解决方案:

1-离线安装传单:npm install leaflet.offline@next

2-将离线传单包导入您的React组件中:

代码语言:javascript
复制
import L from "leaflet"; // Remember that this must also be imported
import "leaflet.offline";

现在看一看旧解决方案中的第6步。现在我们不再使用"generateOfflineTilelayer“和"generateControlSavetiles",而是分别使用L.tileLayer.offline和L.control.savetiles。如果您像我一样使用TypeScript,请在代码线上添加一个ts-忽略作为注释,以防止由TypeScript引起的任何错误。因此,步骤6中的useEffect代码现在如下所示:

代码语言:javascript
复制
useEffect(() => {
  if(map){

    // @ts-ignore
    const tileLayerOffline = L.tileLayer.offline(
      "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png",
      {
        attribution: '&copy; <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-忽略“。希望这对某人有帮助:)

旧解决方案:

好吧,所以我从来没有在网上找到过解决这个问题的人,但是经过一些反复的尝试,我已经成功了。我之所以希望能够在传单中下载地图供离线使用,是因为我正在制作一款带有Ionic、电容和reason的移动电话应用程序。也许值得一提的是,我也在使用打字本。

为了其他人的利益,我将在下面发布一个指南,说明我是如何做到这一点的。希望这能阻止其他人经历我所做过的同样的挫折。

因此,我在Leaflet.offline插件上遇到的问题是,Leaflet.tileLayer.offline或Leaflet.control.saveTiles没有被识别(可能是因为使用了React )。下面是我为使离线地图正常工作所采取的步骤:

我最初是通过npm软件包使用leaflet.offline的。我们希望改变插件,使我们不再依赖插件的使用Leaflet.tileLayer.offline或Leaflet.control.saveTiles。我们想要的是创建一些返回这两个类的实例的方法,然后我们可以将这些方法导入到我们的反应性组件中。最简单的方法是不通过npm使用插件,而是直接下载插件的文件。因此,您应该做的第一件事是下载在插件的GitHub-页面(https://github.com/allartk/leaflet.offline/tree/master/src)上找到的传单.脱机/src文件夹的内容的副本。您应该下载的文件是ControlSaveTiles.js、TileLayerOffline.js和TileManager.js。

2-现在创建一个文件夹在您的反应项目。我把我的名字命名为LeafletMapOfflinePlugin,但你可以随便给它起什么名字。然后将下载的文件移到此文件夹中。

3-打开TileLayerOffline.js文件,并将以下代码粘贴到文件的底部。这将导出一个可用于创建TileLayerOffline类的新实例的函数,以便我们不再依赖于L.tileLayer.offline:

代码语言:javascript
复制
// 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:

代码语言:javascript
复制
// 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.现在,通过使用下列导入,可以将它们导入到任何反应性组件中:

代码语言:javascript
复制
import { generateOfflineTilelayer } from "<path-to-TileLayerOffline.js>";
import { generateControlSavetiles } from "<path-to-ControlSaveTiles.js>";

6-下面可以看到一个简单的示例,说明如何在React组件(使用TypeScript)中使用该功能。在这里,我们使用MapContainer存储useState对象,并使用它在useEffect中手动设置tileLayer和控件:

代码语言:javascript
复制
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: '&copy; <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-你现在应该有一个简单的传单地图与控制元素,当"+“(不要混淆"+”用于缩放。"+“是folet.line的控件元素的默认值,可以通过点击传单.脱机文档来更改,它会下载并保存当前在地图上可见的区域的地图块。如果需要,您可以通过访问web浏览器的“网络”选项卡来检查这些瓷砖的下载情况。当单击"-“(同样,不要被缩放按钮混淆)时,所有下载的瓷砖都会被删除。请参阅下面的图像,说明在使用传单.脱机的ControlSaveTiles时,地图应该是什么样子;保存瓷砖的控件元素位于缩放的控制元素下面:

好吧,那就把它包装起来。希望这对某人有所帮助:D还提供了与传单地图相关的提示;如果只显示一小部分地图有问题,请使用map.invalidateSize() (如果您的地图容器存储为" map ")。这将重置并更新传单地图所知道的设备宽度,希望这将使地图呈现正确:D。

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/69091797

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档