gatsby
Traveling is fun and we all have a lot of places we want to visit, but rarely do we have time to do it all at once. That’s what bucket lists are for! How can we create a custom mapping app that we can show all of our the destinations on our bucket list?
旅行很有趣,我们都有很多想去的地方,但是很少有时间一次去做。 这就是存储桶列表的用途! 我们如何创建一个自定义地图绘制应用程序,以便可以在存储桶列表中显示所有目的地?
Step 2: Creating and managing a list of travel locations with GraphCMS
Step 3: Querying our GraphCMS location data with Gatsby and GraphQL
Step 4: Creating a bucket list of destinations and adding them to the map
我们要建造什么? (What are we going to build?)
We’re going to build a mapping app with Gatsby managed by a CMS that will both display markers on a map and show our locations in a simple text-based list for our bucket list locations.
我们将使用由CMS管理的盖茨比(Gatsby)构建一个地图应用程序,该应用程序既可以在地图上显示标记,又可以在基于文本的简单列表中显示我们的存储桶列表位置的位置。
We’ll spin up the app with a Gatsby Starter for Leaflet and then we’ll use GraphCMS to create and manage the list of locations for our map!
我们将使用Gatsby Starter for Leaflet启动应用程序,然后使用GraphCMS创建和管理地图的位置列表!
哇,地图应用? (Woah, a mapping app?)
Yup. If you haven't played with maps before, don't be discouraged! It's not as bad as you probably think. If you'd rather start with mapping basics, you can read more about how mapping works first.
对。 如果您以前从未玩过地图,请不要气!! 它并不像您想象的那么糟糕。 如果您想开始使用映射基础知识,则可以阅读有关映射如何首先工作的更多信息 。
步骤1:使用Gatsby Starter Leaflet创建新应用 (Step 1: Creating a new app with Gatsby Starter Leaflet)
We’ll start off with Gatsby Starter Leaflet. This is going to give us a basic React application with our mapping tools already built in.
我们将从Gatsby Starter Leaflet开始。 这将为我们提供一个已经内置了映射工具的基本React应用程序。
使用Gatsby Starter Leaflet创建新的Gatsby应用 (Creating a new Gatsby app with Gatsby Starter Leaflet)
To get started, navigate to where you want to create your new app and run:
首先,请导航至要创建新应用的位置并运行:
gatsby new my-travel-bucket-list https://github.com/colbyfayock/gatsby-starter-leaflet
Note: you can replace my-travel-bucket-list
with whatever you want. This will be used to create the new folder for the app.
注意:您可以使用所需的任何内容替换my-travel-bucket-list
。 这将用于为应用创建新文件夹。
Once you run that, Gatsby will pull down the Starter and install the dependencies. After it’s complete, navigate to that directory and run the development command:
运行该文件后,Gatsby将拉下Starter并安装依赖项。 完成后,导航到该目录并运行开发命令:
cd my-travel-bucket-list
yarn develop
# or
npm run develop
Once it’s finished location, your app should be ready to go!
定位完成后,您的应用应该可以使用了!
清理我们的一些演示代码 (Cleaning our some demo code)
Because we’re using a Starter, it has a little bit of demo code. Let’s clean that out to avoid any confusion.
因为我们使用的是Starter,所以它具有一些演示代码。 让我们清理一下以避免混淆。
Open up the src/pages/index.js
file.
打开src/pages/index.js
文件。
First, remove everything inside of mapEffect
except the first line and set up an alias for leafletElement
to map
:
首先,删除里面的一切mapEffect
除了第一行,并设置了一个别名leafletElement
到map
:
async function mapEffect({ leafletElement: map } = {}) {
if ( !map ) return;
}
With that gone, we can remove the markerRef
definition at the top of the IndexPage
component, remove the ref={markerRef}
prop from our <Marker>
component, and the useRef
import next to React.
与走了,我们可以删除markerRef
在顶部定义IndexPage
分量,取出ref={markerRef}
从我们的丙<Marker>
分量,并且useRef
导入下一个React。
Now, we can remove all of the variables that start with popup
and time
, including:
现在,我们可以删除所有以popup
和time
开头的变量,包括:
- timeToZoom timeToZoom
- timeToOpenPopupAfterZoom timeToOpenPopupAfterZoom
- timeToUpdatePopupAfterZoom timeToUpdatePopupAfterZoom
- popupContentHello popupContentHello
- popupContentGatsby popupContentGatsby
Lastly, you can remove all of the following lines:
最后,您可以删除以下所有行:
import L from 'leaflet';
...
import { promiseToFlyTo, getCurrentLocation } from 'lib/map';
...
import gatsby_astronaut from 'assets/images/gatsby-astronaut.jpg';
...
const ZOOM = 10;
Once done, we should be ready to go with a basic app with a map!
完成后,我们应该准备使用带有地图的基本应用程序!
步骤2:使用GraphCMS创建和管理旅行地点列表 (Step 2: Creating and managing a list of travel locations with GraphCMS)
创建一个GraphCMS帐户 (Creating a GraphCMS account)
To get started with GraphCMS, you’ll need an account. I’m not going to walk you through this part, but the good news is they have a generous free tier that makes it easy to sign up for us to use for our demo!
要开始使用GraphCMS,您需要一个帐户。 我不会在这一部分介绍您,但是好消息是,它们有一个免费的免费套餐,可让您轻松注册以供我们用于演示!
Alternatively, if you already have an account, you can make sure you’re logged in.
或者,如果您已经有一个帐户,则可以确保已登录。
创建一个新的GraphCMS项目 (Creating a new GraphCMS project)
Once logged in, we’ll want to create a new project. We’re going to create one manually, so once at the GraphCMS Dashboard, select Create new project:
登录后,我们将要创建一个新项目。 我们将手动创建一个,因此在GraphCMS仪表板中 ,选择一次Create new project :
Here, you can enter whatever you’d like for the Name and Description such as:
在这里,您可以输入任何想要的名称和描述,例如:
- Name: My Travel Bucket List 名称:我的旅行清单
- Description: The locations that I want to travel to some day! 说明:我想去的地方一天!
Below that you’ll see a map where you’ll select a Region. This is where your database data will live, so while it probably doesn’t matter too much for our purposes, you can choose the one that’s closest to you.
在其下方,您将看到一个地图,您将在其中选择一个地区 。 这是您的数据库数据所在的位置,因此,对于我们而言,这也许无关紧要,但您可以选择最接近您的数据。
After you select your options, go ahead and click Create Project.
选择选项后,继续并点击创建项目 。
Next, you’ll be presented with billing options. Since we’re just creating a demo, under Personal select Continue at which point we’ll be dropped into our new GraphCMS project dashboard.
接下来,将为您提供计费选项。 由于我们只是在创建演示,因此在“ 个人”下选择“ 继续” ,这时我们将被放入新的GraphCMS项目仪表板中。
使用GraphCMS创建新的内容模型架构 (Creating a new Content Model Schema with GraphCMS)
In GraphCMS, a Content Model refers to a specific type of data that has specific properties associated with it. In our case, our Model will be a Destination, which will be defined by a Name and a Location.
在GraphCMS中,内容模型是指具有特定属性的特定数据类型。 在我们的例子中,我们的模型将是一个目的地,它将由一个名称和一个位置定义。
First, navigate to the Schema section of GraphCMS in the left sidebar and select Create Model.
首先,导航到左侧栏中GraphCMS的Schema部分,然后选择Create Model 。
Once selected, you’ll see a popup that asks for a bit more information. Here, you can type in “Destination” as the Display Name, which will also fill in most of the other fields. We’ll leave those as is.
选择之后,您会看到一个弹出窗口,要求提供更多信息。 在这里,您可以输入“目的地”作为显示名称 ,这还将填写其他大多数字段。 我们将其保留。
Feel free to add a description if you’d like, but it’s not required. Then select Create model.
如有需要,可以随意添加描述,但这不是必需的。 然后选择创建模型 。
Now that we have our Model, we need our properties.
现在我们有了模型,我们需要属性。
First, select Single line text in the right list of fields and add a Display Name of “Name”. This will also fill out App Id which you can leave as is. Then click Create.
首先,在右侧的字段列表中选择“ 单行文本” ,然后添加“名称”的显示名称 。 这还将填写您可以保留的应用ID 。 然后点击创建 。
Next, scroll down in the field options on the right and under Location select Map. Add “Location” as the Display Name, which will set the App Id as “location” which you can leave as is. Then same as before, click Create.
接下来,向下滚动右侧的字段选项,然后在“ 位置”下选择“ 地图” 。 添加“位置”作为显示名称 ,这会将应用程序ID设置为“位置”,您可以保留原样。 然后与以前一样,单击创建 。
Now we have a Content Model which we’ll use to create our locations!
现在我们有了一个内容模型,我们将使用它来创建位置!
创建我们的位置 (Creating our locations)
Finally, let’s create our locations. Navigate over to Content in the GraphCMS dashboard, make sure you’ve selected Destination under System (should be the only one), and select Create New.
最后,让我们创建位置。 导航到GraphCMS仪表板中的“ 内容 ”,确保已选择“ 系统 ”下的“ 目标 ”(应该是唯一的),然后选择“ 新建” 。
Now we can start adding all of our locations! First, add the name of your location in the Name field, then you can use the Search box under Location to find that location on the map.
现在,我们可以开始添加所有位置! 首先,在名称字段中添加位置的名称 ,然后可以使用位置下的搜索框在地图上找到该位置。
Once you’re good, hit Save and publish. This will create your first location!
一切正常后,点击保存并发布 。 这将创建您的第一个位置!
Follow those same steps and create as many locations as you want.
遵循相同的步骤,并根据需要创建任意多个位置。
We’ll use these for our map and bucket list.
我们将这些用于我们的地图和存储区列表。
步骤3:使用Gatsby和GraphQL查询我们的GraphCMS位置数据 (Step 3: Querying our GraphCMS location data with Gatsby and GraphQL)
Now that we have our locations, let’s use them!
现在我们有了我们的位置,让我们使用它们吧!
向Gatsby添加插件以查询我们的GraphQL数据 (Adding a plugin to Gatsby to query our GraphQL data)
First, we need to add a new plugin to our Gatsby project to query our GraphQL data. In your terminal make sure your development server isn’t running and run:
首先,我们需要在Gatsby项目中添加一个新插件来查询GraphQL数据。 在您的终端中,确保您的开发服务器未运行并且正在运行:
yarn add gatsby-source-graphql
# or
npm install gatsby-source-graphql
Next, open up your gatsby-config.js
file in the root of your project and add the following to your plugins:
接下来,在项目的根目录中打开gatsby-config.js
文件,并将以下内容添加到插件中:
{
resolve: 'gatsby-source-graphql',
options: {
typeName: 'GCMS',
fieldName: 'gcms',
url: '[API ENDPOINT]',
}
}
This will be what sources our data from GraphCMS, but we need an endpoint.
这将是从GraphCMS中获取数据的来源,但是我们需要一个端点。
查找我们的GraphCMS API端点 (Finding our API endpoint for GraphCMS)
Open back up your browser and head over to your GraphCMS project. After selecting Settings in the left navigation, select API Access.
打开备份浏览器,然后转到GraphCMS项目。 在左侧导航栏中选择设置后,选择API访问 。
Before we copy our API Endpoint, first we need to update our permissions so we can query our API. Under Public API Permissions, check the box next to Content from stage Published and click Save.
复制我们的API端点之前,首先,我们需要更新权限,以便可以查询我们的API。 在“ 公共API权限”下 ,选中“ 发布阶段的内容 ”旁边的框,然后单击“ 保存” 。
Next, copy the URL under Endpoints:
接下来,将URL复制到Endpoints下:
And paste that in to your gatsby-config.js
file that we modified above:
并将其粘贴到上面我们修改过的gatsby-config.js
文件中:
{
resolve: 'gatsby-source-graphql',
options: {
typeName: 'GCMS',
fieldName: 'gcms',
url: 'https://[region-id].graphcms.com/v2/[project-id]/master',
},
},
Note: your URL will have actual values inside of [region-id]
and [project-id]
.
注意:您的URL在[region-id]
和[project-id]
内将具有实际值。
Save your gatsby-config.js
file and start your development server backup (yarn develop
) and we’re ready to go!
保存您的gatsby-config.js
文件并开始您的开发服务器备份( yarn develop
),我们准备好了!
通过GraphQL查询我们的位置 (Querying our locations via GraphQL)
Finally, let’s actually query our data so that we’ll be able to use it in our app.
最后,让我们实际查询数据,以便我们可以在应用程序中使用它。
We’re going to create a new React Hook that we’ll be able to use to grab our locations anywhere within our app.
我们将创建一个新的React Hook ,将其用于在应用程序中的任何位置抓取我们的位置。
Under src/hooks/index.js
, add the following line to the existing list:
在src/hooks/index.js
, src/hooks/index.js
下行添加到现有列表中:
export { default as useDestinations } from './useDestinations';
This will allow us to more conveniently import our hook which we’ll create next.
这将使我们能够更方便地导入我们接下来将创建的钩子。
Under src/hooks
, create a new file useDestinations.js
and paste in this code:
在src/hooks
,创建一个新文件useDestinations.js
并粘贴以下代码:
import { graphql, useStaticQuery } from 'gatsby';
export default function useDestinations() {
const { gcms = {} } = useStaticQuery( graphql`
query {
gcms {
destinations {
id
name
location {
latitude
longitude
}
}
}
}
` );
let { destinations } = gcms;
return {
destinations,
};
}
Here, we’re:
在这里,我们是:
Importing the
graphql
anduseStaticQuery
utilities from Gatsby从Gatsby导入
graphql
和useStaticQuery
实用程序- We’re creating a new function (or hook) that is exported by default 我们正在创建一个默认导出的新函数(或挂钩)
In that function, we’re using
useStaticQuery
to create a new GraphQL query which asks GraphCMS to return the data structure we defined.在该函数中,我们使用
useStaticQuery
创建一个新的GraphQL查询,该查询要求GraphCMS返回我们定义的数据结构。That query returns a value which we destructure immediately to grab the
gmcs
object该查询返回一个值,我们立即对其进行解构以获取
gmcs
对象We destructure
destinations
fromgmcs
and return it as part of a new object from our hook我们从
gmcs
解构destinations
,并将其作为钩子中新对象的一部分返回
With this, we can now use our hook anywhere in our app!
有了这个,我们现在可以在应用程序中的任何地方使用钩子了!
Head over to your src/pages/index.js
file, first import our new hook:
转到您的src/pages/index.js
文件,首先导入我们的新钩子:
import { useDestinations } from 'hooks';
And at the top of the IndexPage
component, query our data:
在IndexPage
组件的顶部,查询我们的数据:
const { destinations } = useDestinations();
This puts all of our locations into the destinations
variable. We can test that this works by console logging it out:
这会将我们所有的位置都放入destinations
变量中。 我们可以通过控制台注销来测试它是否有效:
console.log('destinations', destinations);
And once we open up our browser and look in our web developer tools console, we can see our location data!
打开浏览器并查看Web开发人员工具控制台后,便可以看到我们的位置数据!
步骤4:建立目的地的清单清单,并将其加入地图 (Step 4: Creating a bucket list of destinations and adding them to the map)
We’re going to start with creating a simple text list of our destinations. This will let us see all of our destinations in an easy to read format.
我们将从创建一个简单的目的地文本列表开始。 这将使我们以易于阅读的格式查看所有目的地。
创建目的地的文本列表 (Creating a text list of our destinations)
Inside of our IndexPage
and above “Still Getting Started?”, let’s add the following code:
在我们的IndexPage
以及“还在入门吗?”上方,让我们添加以下代码:
<h2>My Destinations</h2>
<ul>
{ destinations.map(destination => {
const { id, name } = destination;
return <li key={id}>{ name }</li>
})}
</ul>
This code:
这段代码:
- Adds a new header for our list 为我们的列表添加新的标题
- Creates a new unordered list 创建一个新的无序列表
Loops through our
destinations
and creates a new list item for each destination that include’s the location’s name遍历我们的
destinations
并为每个目的地创建一个新的列表项,其中包括位置名称
Once we hit save and reload, we should see our list under our map!
点击保存并重新加载后,我们应该在地图下看到我们的列表!
The list looks a little odd though right? We probably want to format it a little better to fit into the page.
这个列表看起来有些奇怪,对吧? 我们可能希望对其进行格式化,使其更适合页面。
Open up src/assets/stylesheets/pages/_home.scss
and inside of the .home-start
class, add:
打开src/assets/stylesheets/pages/_home.scss
并在.home-start
类的内部,添加:
.home-start {
...
ul {
list-style: none;
padding: 0;
margin: 1.2em 0;
}
Let’s also modify the h2
to space things out a little better:
让我们还修改h2
以便更好地将内容间隔开:
.home-start {
...
h2 {
margin-top: 2em;
&:first-child {
margin-top: 0;
}
}
Once you hit save and reload, it should look a little better.
点击保存并重新加载后,它看起来应该会好一点。
Feel free to make additional changes, but we’ll leave it there for now.
随时进行其他更改,但我们暂时将其保留。
将我们的目的地添加到地图 (Adding our destinations to the map)
Now we can finally add our destinations to the map!
现在,我们终于可以将目的地添加到地图了!
Inside of our <Map>
component, we already have a <Marker>
. This allows us to easily add a marker to the map given a position. We’ll take this concept and combine it with our text list to add our locations to the map.
在我们的<Map>
组件内部,我们已经有一个<Marker>
。 这使我们可以轻松地将标记添加到给定位置的地图上。 我们将采用这个概念,并将其与文本列表结合起来,以将我们的位置添加到地图中。
Let’s update our <Map>
code to match the following:
让我们更新<Map>
代码以匹配以下内容:
<Map {...mapSettings}>
{ destinations.map(destination => {
const { id, name, location } = destination;
const position = [location.latitude, location.longitude];
return <Marker key={id} position={position} />
})}
</Map>
Here we:
在这里,我们:
Loop through our
destinations
to dynamically create a new list of components inside our<Map>
遍历
destinations
以动态地在我们的<Map>
创建新的组件列表。Inside each loop instance, we destructure our date from
destination
在每个循环实例中,我们从
destination
解构日期We create a new
position
array with the latitude and longitude我们使用纬度和经度创建一个新的
position
数组Create a new
Marker
where we use our position to add it to the map在我们使用我们的位置将其添加到地图的位置创建一个新的
Marker
This gives us our markers on the map!
这使我们在地图上标记了!
But we want to know what each of those locations are, so let’s also add a popup to each marker that will show the name.
但是我们想知道这些位置中的每一个,因此我们还要为每个显示名称的标记添加一个弹出窗口。
First, we need to import Popup
from react-leaflet
:
首先,我们需要从react-leaflet
导入Popup
:
import { Marker, Popup } from 'react-leaflet';
Then, let’s update our <Marker>
component to return:
然后,让我们更新<Marker>
组件以返回:
return (
<Marker key={id} position={position}>
<Popup>{ name }</Popup>
</Marker>
);
And once we save and open back up our map, you can now click on each marker and see our destinations name!
保存并打开我们的地图后,您现在可以单击每个标记并查看我们的目的地名称!
在完成之前,将地图居中 (Before we’re done, center the map)
Previously, our demo map centered on Washington, DC. Let’s update that to the center of the world since our map doesn’t focus on the United States.
以前,我们的演示地图以华盛顿特区为中心。 让我们将其更新到世界中心,因为我们的地图不关注美国。
Update the LOCATION
variable to:
将LOCATION
变量更新为:
const LOCATION = {
lat: 0,
lng: 0,
};
And with that, we have our map!
有了这些,我们就有了地图!
我们还可以将其他功能添加到我们的应用程序中吗? (What else other features can we add to our app?)
添加一种检查每个位置的方法 (Add a way to check off each location)
Inside GraphCMS, you can add a new field to your Destination content model that allows you to select whether you visited each location or not.
在GraphCMS中,您可以向目标内容模型添加一个新字段,该字段允许您选择是否访问了每个位置。
With this value, we can add it to our query and update our map with some kind of indicator like a checkmark to show that we’ve checked it off our bucket list!
使用此值,我们可以将其添加到查询中,并使用诸如对勾标记之类的指示符更新我们的地图,以表明我们已从存储桶列表中将其选中!
自定义您的地图背景样式 (Customize your map background styles)
We’re using a public version of OpenStreetMap which is open source, but Mapbox offers some cool maps we can use to make it look a little more impressive.
我们使用的是开放源代码的OpenStreetMap的公共版本,但是Mapbox提供了一些很酷的地图,我们可以使用它们使它看起来更令人印象深刻。
If you want to get started changing your map styles, you can check out this other walkthrough of mine to learn how to use Mapbox.
如果您想开始更改地图样式,可以查看我的其他演练以了解如何使用Mapbox。
Check out the blog post or watch the video!
使用自定义图像设置地图标记的样式 (Style the map markers with a custom image)
You can check out my video walk through on how to change the markers to a custom image.
您可以查看我的视频演练,了解如何将标记更改为自定义图像。
Take that a step further and use the feature above to dynamically show a different marker image when you’ve checked off a location.
进一步检查该位置,并在检查位置后使用上述功能动态显示其他标记图像。
Check out the video on Egghead.io!
想更多地了解地图? (Want to learn more about maps?)
Check out some of my other tutorials and videos:
看看我的其他一些教程和视频:
Mapping with React Leaflet (egghead.io)
使用React Leaflet ( egghead.io )进行映射
How to create a Coronavirus (COVID-19) Dashboard & Map App with Gatsby and Leaflet (colbyfayock.com)
如何使用Gatsby和Leaflet (colbyfayock.com) 创建冠状病毒(COVID-19)仪表盘和地图应用
How to Create a Summer Road Trip Mapping App with Gatsby and Leaflet (colbyfayock.com)
如何使用Gatsby和Leaflet (colbyfayock.com) 创建夏季公路旅行地图绘制应用程序
How to build a mapping app in React the easy way with Leaflet (colbyfayock.com)
如何使用Leaflet (colbyfayock.com) 在React中轻松构建地图应用
Anyone Can Map! Inspiration and an introduction to the world of mapping (colbyfayock.com)
任何人都可以地图! 启发和对地图世界的介绍 (colbyfayock.com)
您的旅行清单上有什么? (What’s on your travel bucket list?)
gatsby