本文共 17366 字,大约阅读时间需要 57 分钟。
gatsby
The Christmas season is a magical time of year. We have Santa flying around spreading cheer and Elf roaming around New York during our yearly rewatch with family and friends.
圣诞节是一年中不可思议的时期。 在与家人和朋友的年度重看期间,我们在圣诞老人的欢呼声中四处飞扬,在纽约四处漫游的精灵。
To get in the spirit, we’re going to spin up a web app that includes a map that tracks Santa on it!
为了振作精神,我们将启动一个网络应用程序,其中包括一个在其上跟踪圣诞老人的地图!
Edit 12/23: Updated the app to request directly to Santa's route, just in case the original API doesn't work as originally expected.
编辑12/23:更新了应用程序,以直接请求圣诞老人的路线,以防万一原始API不能按预期运行的情况。
We’re going to work through building a mapping app that tracks Santa’s route and his current location.
我们将通过构建一个映射应用程序来工作,该应用程序可跟踪圣诞老人的路线及其当前位置。
To achieve this, we’re going to spin up a premade Gatsby starter that will give us a basic foundation for a map, utilize Google’s unofficial API to grab Santa’s route, and overlay his position and route on top of the map with Leaflet.
为了实现这一目标,我们将准备一个预制的盖茨比启动器,该启动器将为我们提供地图的基本基础,利用Google的非官方API来获取圣诞老人的路线,并使用Leaflet将其位置和路线叠加在地图上。
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 first.
对。 如果您以前从未玩过地图,请不要气!! 它并不像您想象的那么糟糕。 如果您想开始使用映射基础知识,则可以首先 。
For this exercise, I’m going to assume you have or installed. For each example, I'll use yarn, but use the tool of your choice.
对于本练习,我将假设您已安装或 。 对于每个示例,我将使用yarn,但是使用您选择的工具。
You’ll also want to install globally which will allow us to use their .
您还需要在全球范围内安装 ,这将使我们能够使用其 。
To set up Gatsby’s CLI, run the following command:
要设置盖茨比的CLI,请运行以下命令:
yarn global add gatsby-cli
After, you should be able to run gatsby -h
to see the available commands, which means it’s successfully installed.
之后,您应该能够运行gatsby -h
来查看可用的命令,这意味着它已成功安装。
For more info about the Gatsby CLI, you can .
有关Gatsby CLI的更多信息,您可以 。
Once our command line tools are set up, the first thing we’ll want to do is create a new Gatsby project using I put together. It provides us with a basic setup with and .
设置完命令行工具后,我们要做的第一件事就是使用我放在一起程序创建一个新的Gatsby项目。 它为我们提供了和的基本设置。
Starting in your project directory, let’s install the project:
从项目目录开始,让我们安装项目:
gatsby new [directory] https://github.com/colbyfayock/gatsby-starter-leaflet
Make sure to replace [directory]
with the location you want to set up your project.
确保将[directory]
替换为您要设置项目的位置。
Once you run that command, Gatsby will clone that project without any of the git references and install the packages required to start.
一旦您运行了该命令,Gatsby将在没有任何git引用的情况下克隆该项目,并安装启动所需的软件包。
To make sure it works, you can now navigate to that directory, spin up your server, and test it in the browser:
为了确保其正常工作,您现在可以导航到该目录,启动服务器,然后在浏览器中对其进行测试:
cd [directory]yarn develop
Where you see [directory]
above, make sure to use the same path as you did before when setting up the new Gatsby project.
在上方的[directory]
,请确保使用与设置新Gatsby项目时相同的路径。
If all goes as planned, your server should start and you should now be able to see your basic mapping app in your browser!
如果一切按计划进行,则服务器将启动,您现在应该可以在浏览器中看到基本的地图应用程序!
This starter comes with a quick example of how we can interact with the map. We're not going to need this at all for our purposes so we can go ahead and clean things up.
此入门指南提供了一个有关如何与地图进行交互的快速示例。 为了我们的目的,我们根本不需要它,因此我们可以继续进行清理。
To start, we’re going to open up our index.js
file, the homepage file, and get rid of everything inside of the mapEffect
function, which leaves us with:
首先,我们将打开index.js
文件(即主页文件),并摆脱mapEffect
函数内部的所有内容,从而使我们拥有:
// In src/pages/index.jsasync function mapEffect({ leafletElement } = {}) { // Get rid of everything in here}
Now, let’s remove the Marker
component nested inside of our Map
, so we end up with:
现在,让我们删除嵌套在Map
内的Marker
组件,最后得到:
Now that we’re no longer using that functionality, we can get rid of the variables and references at the top of the file, so you can go ahead and remove:
现在我们不再使用该功能,我们可以摆脱文件顶部的变量和引用,因此可以继续删除:
Now that we’re in a good place, let’s get our hands dirty and find Santa. To do this, we’re going to use Google’s unofficial, undocumented API. This means that it’s possible this API won’t be available the day after this get’s published, but let’s be optimistic.
现在我们处于一个好的地方,让我们动起来,找到圣诞老人。 为此,我们将使用Google的非官方,未记录的API。 这意味着该API发布后的第二天可能将不可用,但是让我们保持乐观。
Additionally, at the time of writing, it’s still showing last year’s destinations, so what we’re really going to be visualizing here is Santa’s previous year’s route, though the hope is this would reset on the 24th and we’ll all be merry!
此外,在撰写本文时,它仍在显示去年的目的地,因此我们真正要在这里看到的是圣诞老人的前一年路线,尽管希望这会在24日重置,并且我们都会很高兴!
Before we get Santa, let’s first add a line back to our mapEffect
function:
在获得圣诞老人之前,让我们先在mapEffect
函数中添加一行:
async function mapEffect({ leafletElement } = {}) { if ( !leafletElement ) return;}
What this will do is prevent the rest of our code from running in the event our map isn't ready yet. The mapEffect
function itself, as you can see in the Map
component, runs inside of an instance of useEffect
passing an argument of a ref
to the map, allowing us to run some code after our component renders.
这样做是为了防止我们的其余代码在地图尚未准备好时运行。 如您在Map
组件中所见, mapEffect
函数本身在useEffect
实例内部运行,该实例将ref
的参数传递给map,从而使我们能够在组件渲染后运行一些代码。
So once we have that line, let’s now fetch Santa’s route inside of our mapEffect
function:
因此,一旦有了这一行,现在就可以在mapEffect
函数中获取圣诞老人的路线:
async function mapEffect({ leafletElement } = {}) { if ( !leafletElement ) return; let route, routeJson; try { route = await fetch('https://firebasestorage.googleapis.com/v0/b/santa-tracker-firebase.appspot.com/o/route%2Fsanta_en.json?alt=media&2018b'); routeJson = await route.json(); } catch(e) { console.log(`Failed to find Santa!: ${e}`); } console.log(‘routeJson’, routeJson);}
Let’s break this down:
让我们分解一下:
Finally, we just log
out our response for now
最后,我们暂时log
响应
Now we have Santa and his route, which means we can see all the destinations in his route. If you dig in the response a little bit, you can see some fun things like how many presents were delivered to each location and the weather at the time!
现在我们有了圣诞老人和他的路线,这意味着我们可以看到他的路线中的所有目的地。 如果您仔细研究一下响应,您会发现一些有趣的事情,例如,每个地点已送出多少礼物以及当时的天气!
We found Santa! 🎉 Now let’s put him on the map.
我们找到了圣诞老人! 🎉现在让我们把他放在地图上。
For our purposes, we’ll need to find the latitude and longitude of Santa. The problem is, we don’t get this exact value defined anywhere, we just get his destinations.
为了我们的目的,我们需要找到圣诞老人的经度和纬度。 问题是,我们没有在任何地方定义这个确切的值,我们只是得到他的目的地。
Since we don’t have his location specified anywhere, we can utilize his last known location where presents were delivered. Add the following after our last snippet inside the mapEffect
function:
由于我们没有在任何地方指定他的位置,因此我们可以利用他最后一次知道礼物递送的位置。 在mapEffect
函数内的最后一个片段之后添加以下内容:
const { destinations = [] } = routeJson || {}; const destinationsVisited = destinations.filter(({arrival}) => arrival < Date.now()); const destinationsWithPresents = destinationsVisited.filter(({presentsDelivered}) => presentsDelivered > 0);const lastKnownDestination = destinationsWithPresents[destinationsWithPresents.length - 1]
Below our request code, we:
在我们的请求代码下方,我们:
Destructure routeJson
to grab destinations
into a constant, adding a fallback to an empty object
routeJson
以将destinations
捕获为常量,从而向空对象添加后备
At this point in time, 12/23, we don't actually have any destinations, as Santa is still at the North Pole. At any time, we can test this out to simulate a future date by replaceing Date.now()
in destinationsVisited
with a future date, such as 1577188980000
which would be around 7pm Eastern on 12/24. With that change, we can see what Santa's route actually looks like!
目前时间12/23,我们实际上没有任何目的地,因为圣诞老人仍在北极。 在任何时候,我们都可以通过使用将来的日期(例如1577188980000
,将在12/24东部时间晚上7点左右Date.now()
destinationsVisited
Date.now()
来测试该日期,以模拟将来的日期。 有了这一更改,我们可以看到圣诞老人的路线实际上是什么样子!
Now that it's close to Christmas, Santa will still be at the North Pole, so let's handle the case where we don't have a location.
现在临近圣诞节,圣诞老人仍将在北极,所以让我们来处理一下我们没有地点的情况。
Above the line where we set lastKnownDestination
, let's add:
在我们设置lastKnownDestination
的行lastKnownDestination
,让我们添加:
if ( destinationsWithPresents.length === 0 ) { // Create a Leaflet Market instance using Santa's LatLng location const center = new L.LatLng( 0, 0 ); const noSanta = L.marker( center, { icon: L.divIcon({ className: 'icon', html: `🎅`, iconSize: 50 }) }); noSanta.addTo( leafletElement ); noSanta.bindPopup( `Santa's still at the North Pole!` ); noSanta.openPopup(); return;}
Okay so what are we doing here?
好吧,我们在这里做什么?
This was a section added after published to handle the API resetting, but you can still follow along with the code I added in context of the rest of the rest of the code.
这是发布后添加的用于处理API重置的部分,但是您仍然可以在其余的代码中跟随我添加的代码。
Edit 12/23: This section was originally written with the previous year's API, but this is still a good example of what you'll expect on the response, so you can follow right along.
编辑12/23:此部分最初是使用上一年的API编写的,但这仍然是您期望得到响应的一个很好的示例,因此您可以继续进行。
And as we can see, since we’re looking at last year’s data, Santa is back home at the North Pole.
正如我们所看到的那样,由于我们正在查看去年的数据,因此圣诞老人回到了北极。
With his location, we can pull that apart, set up a Leaflet marker instance, and add our old friend to the map. Add the following after our last snippet inside the mapEffect
function:
通过他的位置,我们可以将其拆开,设置一个Leaflet标记实例,然后将我们的老朋友添加到地图上。 在mapEffect
函数内的最后一个片段之后添加以下内容:
const santaLocation = new L.LatLng( lastKnownDestination.location.lat, lastKnownDestination.location.lng );const santaMarker = L.marker( santaLocation, { icon: L.divIcon({ className: ‘icon’, html: `🎅`, iconSize: 50 })});santaMarker.addTo(leafletElement);
Here we:
在这里,我们:
If we refresh our page, you’ll have to zoom out and pan up a little bit, but we'll see Santa on the map!
如果我们刷新页面,则必须缩小和平移一点,但是我们会在地图上看到圣诞老人!
Before we move on, let’s give Santa a little holiday cheer to make him easier to find. Find your application.scss
file and toss these styles in:
在继续之前,让我们给圣诞老人一个节日的欢呼,使他更容易找到。 找到您的application.scss
文件,并将这些样式折腾为:
// In src/assets/stylesheets/application.scss.icon { & > div { display: flex; justify-content: center; align-items: center; overflow: hidden; border-radius: 100%; box-shadow: 0 3px 4px rgba(0,0,0,.4); border: none; transition: all .2s; &:hover { box-shadow: 0 4px 8px rgba(0,0,0,.6); } }}.icon-santa { width: 50px; height: 50px; font-size: 3em; background: white;}
This just adds a white circle around him, a little drop shadow, and increases the size a bit to make him a little easier to find on the map.
这只会在他周围添加一个白色圆圈,并带有一点阴影,并增加一点大小,使他在地图上更容易找到。
The last thing we’re going to do here is draw a path on the map showing his route so we can follow along.
我们在这里要做的最后一件事是在地图上绘制一条路径,显示他的路线,以便我们继续前进。
To get started, let’s update our code and add this last bit after our last snippet in the mapEffect
function:
首先,让我们更新代码,并在mapEffect
函数中的最后一个片段之后添加最后一点:
// Create a set of LatLng coordinates that make up Santa's routeconst santasRouteLatLngs = destinationsWithPresents.map(destination => { const { location } = destination; const { lat, lng } = location; return new L.LatLng( lat, lng );});// Utilize Leaflet's Polyline to add the route to the mapconst santasRoute = new L.Polyline( santasRouteLatLngs, { weight: 2, color: 'green', opacity: 1, fillColor: 'green', fillOpacity: 0.5});// Add Santa to the map!santasRoute.addTo(leafletElement);
What we’re doing:
我们正在做什么:
What we get… is a bunch of squiggly lines!
我们得到的……是一堆弯曲的线条!
This is expected. This gets technical really fast, but Leaflet by default can only understand 1 “portion” of the map as it wraps around in our browser. What this realistically means, is instead of drawing a line around a globe, the coordinates think it goes from one side of the world to the other as it hits the International Dateline. This is a bit out of scope for this tutorial, but you can check out to learn more and see if you can implement the solution to it.
这是预期的。 这在技术上确实非常快,但是默认情况下,Leaflet在我们的浏览器中环绕时只能理解地图的1个“部分”。 实际上,这意味着与其在全球范围内画一条线,不如说坐标在到达国际日期变更线时从世界的一侧延伸到另一侧。 这在本教程中范围 ,但是您可以查看以了解更多信息,并查看是否可以实现该解决方案。
One last thing! And this is completely optional. Let’s make the map a little bit bigger, set the background color to match our oceans, and zoom out a little bit. So let’s make a few changes:
最后一件事! 这是完全可选的。 让我们将地图放大一点,设置背景颜色以匹配我们的海洋,然后缩小一点。 因此,让我们进行一些更改:
// In src/pages/index.jsconst DEFAULT_ZOOM = 1;
We’re setting our default zoom to 1
instead of 2
to allow the map to be zoomed out a bit.
我们将默认缩放比例设置为1
而不是2
以允许将地图缩小一点。
// In src/assets/stylesheets/pages/_home.scss.page-home { .map, .map-base { height: 80vh; }}
We’re setting our map to a height of 80vh
instead of 50vh
to make it take up a little more of our screen.
我们将地图的高度设置为80vh
而不是50vh
,以使其占据屏幕的一部分。
// In src/assets/stylesheets/components/_map.scss.map { &, .map-base { background: #acd3de; }}
We’re setting the background color of our map to #acd3de
instead of $blue-grey-50
which allows us to match the color of the oceans on our map.
我们将地图的背景色设置为#acd3de
而不是$blue-grey-50
,这使我们能够匹配地图上的海洋颜色。
What this achieves is being able to see Santa’s full route and Santa on the first view. Additionally, since the map only covers part of the screen, setting the background color of the map allows us to not have a little bit of a weird cutoff.
这样实现的是能够在第一视图上看到圣诞老人的完整路线和圣诞老人。 另外,由于地图仅覆盖屏幕的一部分,因此设置地图的背景颜色可使我们没有一点怪异的边界。
To take this 1 step further, follow along with both how we added the routes and Santa to the map and try to see if you can add a marker to each destination location to show where all of the stops are. Bonus, add a popup to each one that says how many presents were delivered to that location!
要进一步执行此步骤,请遵循我们如何将路线和圣诞老人添加到地图上,并尝试查看是否可以在每个目的地位置添加标记以显示所有停靠点。 奖励,向每个弹出窗口添加一个弹出窗口,该弹出窗口指示有多少礼物已发送到该位置!
To see the answer with some code organization and how I added the gift markers, check out the final version of the .
要查看某些代码组织的答案以及我如何添加礼物标记,请查看的最终版本。
While you’re there, you can also see how I utilized Leaflet.Antimeridian to fix our map's route.
在那里,您还可以看到我如何利用Leaflet.Antimeridian来修复地图的路线。
Building basic apps with a map isn’t nearly as bad as we thought! We learned how to fetch some data from an API, grab the data we need, and draw representations of that data on a map.
用地图构建基本应用程序并没有我们想象的那么糟糕! 我们学习了如何从API中获取一些数据,获取所需的数据以及在地图上绘制该数据的表示形式。
Next time you want to add a map widget to your landing page, try Leaflet. Share what you create on ! Would love to see what you come up with.
下次您要将地图小部件添加到目标网页时,请尝试使用Leaflet。 在分享您创建的内容! 很想知道您的想法。
I hope you and your family have a fantastic holiday season!
希望您和您的家人过一个愉快的假期!
You can check out a few of my other resources to get started:
您可以查看其他一些资源以开始使用:
Want to read some of my other articles? Check out my blog:
是否想阅读我的其他文章? 看看我的博客: :
翻译自:
gatsby
转载地址:http://gihwd.baihongyu.com/