WEB程序员笔记

一个前端开发工程师的个人博客

将Next.js与Leaflet.js + Mapbox集成

您想在您的Nextjs应用程序中包括交互式地图吗?然后,您一定遇到过Leafletjs。尽管Leafletjs的使用非常简单,但是在使用Nextjs构建服务器端渲染(SSR)应用程序时,它有时会有些烦人。但是,您不用担心我已经找到了解决方法。

要设置场景,首先让我们知道👇

为什么选择Leafletjs?

Leaflet是领先open-sourcemobile-friendly交互式地图JavaScript库。它仅重约39 KB的JS,它具有mapping features开发人员所需要的所有内容。

Leaflet的目的是尽可能轻巧,并专注于一组核心功能,而扩展其功能的一种简单方法是使用第三方插件。感谢Leaflet背后的强大社区,实际上有数百个不错的插件可供选择。在本文后面的示例中,我们将使用其中一个插件。

讲解

请注意,在本教程中,我假设您已经有一个现有的Next.js项目正在运行。如果不这样做,请先遍历Next.js文档

安装所需的依赖项

npm i leaflet leaflet-defaulticon-compatibility leaflet-geosearch react-leaflet

注意:如果使用TypeScript,请确保安装,@types/leaflet否则在示例中使用的某些属性上会出现编译错误。

我将在本教程中进一步使用它们时解释它们的需求。

创建地图组件

在您的应用程序中,在component文件夹中创建一个map.jsx文件./component/Map.jsx

此代码与嵌入页面的文件位于单独的文件中非常重要,因为否则您将收到窗口未定义的错误,稍后我们将对此进行讨论。

旁注:对于Typescript用户,该文件称为map.tsx。
在文件内部放入以下代码

import { MapContainer, TileLayer,Marker,Popup } from 'react-leaflet'
import 'leaflet/dist/leaflet.css'
import 'leaflet-defaulticon-compatibility/dist/leaflet-defaulticon-compatibility.css'
import "leaflet-defaulticon-compatibility";

const Map = () => {
  return (
    <MapContainer center={[40.8054,-74.0241]} zoom={14} scrollWheelZoom={false} style={{height: "100%", width: "100%"}}>
      <Marker 
      position={[40.8054,-74.0241]}
      draggable={true}
      animate={true}
      >
        <Popup>
          Hey ! you found me
        </Popup>
      </Marker>
    </MapContainer>
  )
}

export default Map

在上面的示例中,我使用了react-leaflet的一些基本属性来初始化地图。

  • center:以所提供的纬度和经度为中心。
  • zoom:地图的初始缩放范围为0到18。
  • scrollWheelZoom:是的,这正是听起来的样子。
  • position:设置标记的位置。
  • draggable:有助于将标记拖放到地图上。
  • animate:如果为true,则平移将始终保持动画状态。

react-leaflet文档中提供了许多功能和示例。

设置Mapbox API

在上面的示例中,我们将使用Mapbox API将自定义标题图层添加到地图中。
传单静静地支持Mapbox插件,它还为您提供了许多自定义映射样式,您甚至可以在其工作室中创建自己的样式,因为本教程的这一部分将使用默认样式。

《将Next.js与Leaflet.js + Mapbox集成》

设置自定义Mapbox样式的第一件事是拥有一个帐户。我不会指导您完成该过程,但是您可以转到Mapbox的网站,免费注册。

为了生成令牌,我们将使用令牌来提供对地图的访问权限。

  • 转到Mapbox信息中心的“帐户”部分,您可以通过单击导航栏右上部分的个人资料来访问它。
  • Mapbox为您提供了一个“默认”令牌,您可以在应用程序中使用它。您可以随意使用它,但是我建议您创建一个新令牌,以提供唯一的名称。

配置我们的自定义端点
在本教程中,我们将使用Mapbox的Static Tiles服务。您可以从此处复制端点,如下所示。

https://api.mapbox.com/styles/v1/{username}/{style_id}/tiles/256/{z}/{x}/{y}@2x?access_token={access_token}

这里需要了解一些参数:

  • username:这将是您的Mapbox帐户的用户名
  • style_id:这将是您使用的样式的ID
  • z, x, y:这些是Leaflet以编程方式交换的参数,因此我们希望保留它们不变
  • access_token:这是您在上方创建的Mapbox键

对于示例的这一部分,我们使用的是Mapbox本身提供的样式。您也可以在Mapbox中创建自己的样式,但现在将使用streets-v11from here

更新端点参数后,最终的tilepoint URL将如下所示:
https://api.mapbox.com/styles/v1/mapbox/streets-v11/tiles/256/{z}/{x}/{y}@2x?access_token=MY_ACCESS_TOKEN

由于样式是由mapbox提供的,因此URL中的用户名将替换为mapbox,如果您使用自己的样式,则将其替换为您自己的用户名。

向React Leaflet添加自定义TileLayer

你的里面<MapContainer>在map.jsx组件,您有一个<TileLayer>组件,它定义了世界的形象,你的基础在地图。

React Leaflet主页上的示例使用OpenStreetMap的公共版本作为TileLayer,这是一个由世界各地的人们创建和更新的开源地图项目。

<MapContainer center={position} zoom={13}>
  <TileLayer
    url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
    attribution="&copy; <a href=&quot;http://osm.org/copyright&quot;>OpenStreetMap</a> contributors"
  />
</MapContainer>

这为您提供了基本的地图,但是我们希望在Mapbox中进行交换,以便我们可以为地图设置自定义外观。

要添加自定义样式,我们将要更新TileLayer组件的urlattribution属性。

对于URL,它只是我们之前创建的自定义样式终结点,因此在我的示例中,它看起来像:

https://api.mapbox.com/styles/v1/mapbox/streets-v11/tiles/256/{z}/{x}/{y}@2x?access_token=MY_ACCESS_TOKEN

对于归因,我们希望将Mapbox归功于服务,因此我们希望将归因设置为:

Map data &copy; <a href=&quot;https://www.openstreetmap.org/&quot;>OpenStreetMap</a> contributors, <a href=&quot;https://creativecommons.org/licenses/by-sa/2.0/&quot;>CC-BY-SA</a>, Imagery &copy; <a href=&quot;https://www.mapbox.com/&quot;>Mapbox</a>

插入TileLayer后,我们的map.jsx现在应如下所示:

import { MapContainer, TileLayer, Marker, Popup } from "react-leaflet";
import "leaflet/dist/leaflet.css";
import "leaflet-defaulticon-compatibility/dist/leaflet-defaulticon-compatibility.css";
import "leaflet-defaulticon-compatibility";

const Map = () => {
  return (
    <MapContainer
      center={[40.8054, -74.0241]}
      zoom={14}
      scrollWheelZoom={false}
      style={{ height: "100%", width: "100%" }}
    >
      <TileLayer
        url={`https://api.mapbox.com/styles/v1/mapbox/streets-v11/tiles/256/{z}/{x}/{y}@2x?access_token=MY_ACCESS_TOKEN`}
        attribution='Map data &copy; <a href=&quot;https://www.openstreetmap.org/&quot;>OpenStreetMap</a> contributors, <a href=&quot;https://creativecommons.org/licenses/by-sa/2.0/&quot;>CC-BY-SA</a>, Imagery &copy; <a href=&quot;https://www.mapbox.com/&quot;>Mapbox</a>'
      />
      <Marker position={[40.8054, -74.0241]} draggable={true} animate={true}>
        <Popup>Hey ! I live here</Popup>
      </Marker>
    </MapContainer>
  );
};

export default Map;

最后,让我们渲染地图

如您所知,全局window对象在SSR中不可用,如果尝试在其中使用它,则会收到ReferenceError。
现在,为了避免这种情况,我们可以利用Nextjs的动态加载优势,这将有助于防止SSR。
在内部./pages/index.js嵌入您的Map组件,如下所示:

import React from "react";
import dynamic from "next/dynamic";

export default function Home() {
  const MapWithNoSSR = dynamic(() => import("../component/map"), {
    ssr: false
  });

  return (
    <main>
      <div id="map">
        <MapWithNoSSR />
      </div>
    </main>
  );
}

这就是您的好选择

总结思想

我希望这个快速教程对您有所帮助。我知道如果在执行Next.js + leafletjs路径之前进行此操作,它将为我节省很多工作。一旦一切顺利,别忘了向我提供宝贵的反馈意见。祝你好运!👍

点赞

发表评论

电子邮件地址不会被公开。 必填项已用*标注