XYZ

This holiday, use your mapping skills to help out others

By Dylan Babbs | 12 December 2018

What if a map doesn't just get you around, but also helps you to help others? As a location platform and mapping company, we’re constantly searching for ways we can use our tech to improve the quality of life for everyone. One of the key values of HERE is giving back and we felt that this season is a good time to bring in our expertise in map making to let you help your local communities.

We've recently established Chicago as our North America headquarters. Throughout this time, we've been working with the Greater Chicago Food Depository on some special projects (more on this soon!) and general volunteer opportunities.

The Food Depository is the Chicago area's largest food bank. In its most recent fiscal year, the Food Depository was responsible for distributing nearly 70 million pounds of food, 38% of which was fresh produce. Every day they provide the equivalent of 159,000 meals to struggling families in our community.

If you're based in the Chicago area and would like to get involved, the Food Depository has plenty on volunteer opportunities available. You can learn more about getting involved with the organization on their official website.

In this tutorial, we’ll learn how to help non-profit organizations directly from your computer by creating a dedicated map with a special dataset: a list of volunteer opportunities at the Food Depository this holiday season. To create this map, we'll be using:

  • HERE XYZ: a new cloud geo storage and visualization service.
  • Tangram: an open-source vector renderer.

This tutorial will consist of two different sections. The first section doesn't require any coding knowledge. We'll be using XYZ Studio to create a map with Food Depository volunteer opportunities simply by dragging and dropping our data. You'll even be able to share or embed this map on your personal website.

The second part will require some basic knowledge around web programming and JavaScript. Don't worry, there won't be anything too advanced, so if you don't feel too comfortable with web programming, feel free to try and follow along.

Let's get started! 

Part 1: XYZ Studio

For those unfamiliar with XYZ Studio, let's take a quick tour. You can access XYZ Studio at xyz.here.com. If you don't already have an account, go ahead and make one--it's free. Once you've signed up or logged in, you should see this view:

xyz-studio

Let's cover some terminology within XYZ Studio:

  • Projects: the different maps made with XYZ Studio.
  • Data Hub: different datasets uploaded to XYZ Studio, which you can then use in your projects.

To get started with our map, we're going to need get ahold of our data first. I've conveniently compiled a list of the Food Depository events in CSV format here. I got a hold of this dataset through manually scraping the Food Depository's website. Feel free to try and recreate this map with the charity of choice. You most likely can acquire similar datasets for your favorite charity on their website.

Go ahead and download this file.

Our dataset has the following columns:

  • Day: the date of the volunteer opportunity
  • Address: the plain text location of the volunteer opportunity
  • Time
  • Title
  • Type: the different type of opportunity (kid's event, repack, etc.)
  • Latitude and Longitude: the coordinates of the volunteer opportunity (geocoded from the address column)

To upload it to XYZ Studio, all you need to do is navigate to the Data Hub tab in the top-level navigation. Once you're there, click Create new dataset and then upload the volunteer opportunity CSV.

What's awesome about XYZ Studio is that it accepts a few different file formats for geo data. You can upload GeoJSON, CSV and Shapefiles. However, if you do choose to upload a CSV file, make sure it has longitude and latitude columns in the file.

Once you are done uploading the CSV to the Data Hub, let's hop over to the Projects tab to create a new map.

I've titled my map something simple for now: "Holiday Map". 

studio2

To add the volunteer opportunities to the map, I can click the button titled +Add and then select the recently uploaded file. And just like that, my map now contains my volunteer opportunity dataset!

Using the tools sidebar on the left side, I can play around with the style of my map. I changed my map to a friendlier and more colorful theme, increased the marker size, and then added 'Food and Drink' icons inside the marker.

studio3

In order to share the map, we'll need to bookmark the initial view. To do that, I can click the bookmark icon in the top center. Next, I'll click the large teal button titled Project Settings to kick off the sharing process. From this next view, I can grab the url or iframe for my newly created map. You can check out my map here:

https://xyz.here.com/viewer/?project_id=2d549553-b61a-48fd-b847-b7b81571db7e

In just a few minutes you were able to create a simple volunteer map inside of XYZ Studio. In the next section, we'll be using the same dataset to create a slightly more customized map with Tangram.

Part 2: Tangram

One of my favorite features about XYZ is XYZ Hub API Spaces. XYZ Hub is a real-time cloud-based location hub for discovering, storing, retrieving, manipulating and publishing private or public mapping data.

So, in short, XYZ Spaces are a great place to store your geo data in the cloud. XYZ Spaces can return your data in GeoJSON or tiled MVT format. Awesome for vector maps!

Whenever you upload a dataset to XYZ Studio inside of Data Hub, XYZ automatically creates a new Space for the dataset. What this means is that the data uploaded into XYZ Studio can also be accessed programmatically via API. This is exactly what we'll be doing with our Tangram map.

To start, we're going to need two things:

  • XYZ Space ID: this can be found in XYZ Studio in the Add Data view.
studio4

Once you've grabbed both of those codes, keep them somewhere handy. We'll be using them shortly.

Let's start writing some code. We're going to be creating four files: an HTML file, a CSS file, a YAML file for our map styles, and a JavaScript file. Sorry React diehards, we're just writing plain old JavaScript today.

Starting with our HTML file, let's create an index.html with the following content:


<!DOCTYPE html>
<html>

<head>
<title>Holiday Season Volunteer Map</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="index.css" />
<link href="https://fonts.googleapis.com/css?family=Montserrat:300,400" rel="stylesheet">
<script src="https://unpkg.com/leaflet@1.3.3/dist/leaflet.js"></script>
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.0.1/dist/leaflet.css" />
<script src="https://unpkg.com/tangram/dist/tangram.min.js"></script>
</head>

<body>
<div id="control">
<div class="title">Greater Chicago Food Depository Volunteer Calendar</div>
<p class="subtitle">An interactive map showing available <a href="https://www.chicagosfoodbank.org/get-involved/" target="_blank">GCFD volunteer opportunities</a> throughout the 2018 holiday calendar.</p>
<p class="subtitle">This map is purely for showcase purposes. If you are interested in volunteering with GCFD, please take a look at the <a href="https://volunteers.chicagosfoodbank.org/index.php?section=IndividualOpportunities&action=calendar" target="_blank">official volunteer calendar</a>.</p>
<div>Key</div>
<div>
<div class="key-label">‼️ Immediate Need</div>
<div class="key-label">🚚 Fresh Truck</div>
<div class="key-label">🌟 Special Events</div>
<div class="key-label">🍱 Repack</div>
<div class="key-label">👶 Kid Friendly Opportunities</div>
</div>
</div>
<div id="map"></div>
<script src="index.js"></script>
</body>

</html>

There's nothing too special going on here, we're just laying out the scaffolding of our site with a map and sidebar (control) div.

As for our CSS, let's create an index.css with the following content:


body, html {
   margin: 0;
   padding: 0;
   border: 0;
   font-family: 'Montserrat', sans-serif;
   color: #333;
}

#map {
   height: 100vh;
   width: 100vw;
}

#control {
   background: white;
   width: 300px;
   padding: 20px;
   margin: 20px;
   right: 0;
   position: absolute;
   z-index: 50000;
   border: 2px solid #0560FD;
   border-radius: 4px;
}

a {
   color: #0560FD;
   text-decoration: none;
}

a:hover {
   text-decoration: underline
}

#control .title {
   font-size: 19px;
}

#control .subtitle {
   color: gray;
   font-size: 14px;
   font-weight: 300;
}

.key-label {
   color: gray;
   font-weight: 400
}

.tooltip-title {
   font-family: 'Montserrat';
   font-size: 19px;
   color: 333;
}

.tooltip-subtitle {
   font-family: 'Montserrat';
   color: gray;
   font-size: 14px;
   font-weight: 300;
}

.leaflet-popup-content-wrapper {
   border: 2px solid #0560FD;
}

canvas {
   pointer-events: none;
   position: absolute;
   top: 0;
   left: 0;
   z-index: 500000
}

Once again, we're just performing some straightforward CSS styling to make sure our map is looking oh so so pretty ☺️.

Onto our JavaScript file. Create an index.js with the following:


const map = L.map('map', {
   center: [41.7317392281872, -87.51007854938509],
   zoom: 11.4,
   layers: [
      Tangram.leafletLayer({
         scene: 'scene.yaml',
         events: {
            hover: showTooltip,
            click: showTooltip
         }
      })
   ],
   zoomControl: false
});

function showTooltip(selection) {
   if (selection.feature) {
      const tooltipHtml = `
<div> class="tooltip-title">${selection.feature.properties.Title}</div>
<div> class="tooltip-subtitle">${selection.feature.properties.Type}</div>
<div> class="tooltip-subtitle">${selection.feature.properties.Day} ${selection.feature.properties.Time}</div>
<div> class="tooltip-subtitle">${selection.feature.properties.Address}</div>`;
      const popup = L.popup()
         .setLatLng(selection.leaflet_event.latlng)
         .setContent(tooltipHtml)
         .openOn(map);
   } else {
      map.closePopup();
   }
}

In the above code, we are initializing our Tangram map with the map variable. We've attached some hover and click events in order to fire up our tooltip when the user hovers or clicks on an icon.

The showTooltip function does just that. We prepare some HTML to insert into the tooltip. When the user hovers or clicks on an icon on the map, we present the tooltip. When the hover or click on a map object other than an icon, we remove the tooltip.

And by now you should know the drill. For the last file, we create a scene.yaml file with the following:

import: refill-style/refill-style.yaml

cameras:
    camera1:
        type: perspective

lights:
    light1:
        type: directional
        direction: [0, 1, -.5]
        diffuse: .3
        ambient: 1

sources:
    xyz_osm:
        type: MVT
        url: https://xyz.api.here.com/tiles/osmbase/256/all/{z}/{x}/{y}.mvt
        max_zoom: 16
    gcfd_events:
        url: https://xyz.api.here.com/hub/spaces/YOUR-XYZ-SPACE-ID/tile/web/{z}_{x}_{y}
        type: GeoJSON
        url_params:
            access_token: YOUR-XYZ-TOKEN

layers:
    gcfd_events:
        data: {source: gcfd_events}
        draw:
           text:
              interactive: true
              optional: false
              collide: false
              repeat_distance: 0
              text_source: |
                  function() {
                       if (feature.Type === 'Immediate Need') {
                          return '‼️';
                       } else if (feature.Type === 'Fresh Truck') {
                          return '🚚';
                       } else if (feature.Type === 'Special Events') {
                          return '🌟';
                       } else if (feature.Type === 'Repack') {
                          return '🍱';
                       } else if (feature.Type === 'Kid Friendly Opportunities') {
                          return '👶';
                       }
                    }
              font:
                  fill: black
                  size: 35px

                  stroke:
                      color: white
                      width: 2px

The YAML file is the fun part! This is where you can write the styling rules for the Tangram map.

Be sure to replace YOUR-XYZ-SPACE-ID and YOUR-XYZ-TOKEN with the codes we grabbed earlier in the section.

Let's take a quick pause and dive deeper into this YAML file.

  • At the top of the file, we are importing an external file from refill-style/refill-style.yaml. This refill style contains the blue map theme we are using.
    • Important! Be sure to download this file and place it into your project directory. You can download the file here.
  • In the Source section, we are importing two different data sources: our base map (from our friends at Tilezen and OpenStreetMap) and our GCFD volunteer opportunities from our XYZ Space.
  • In Layers, we are specifying how we want to style the gcfd_events data. I decided to have some fun with this map and use emojis as icons. To determine which icon to use, I've embedded a JavaScript function inside the text_source key.

Congratulations, we now have a functioning and style map showcasing the locations of GCFD volunteer opportunities.

But let's not stop there...

What is one more thing we can add to make add an extra special touch to this holiday map? Snow! ❄⛄️

To do so, we're going to include one extra JavaScript file: snow.js. Go ahead and download this file and then include it in our HTML right before we import index.js. Additionally, add a canvas element as the first element inside the body.


<canvas id="canvas"></canvas>
<div id="control">...</div>
<div id="map"></div>
<script src="snow.js"></script>
<script src="index.js"></script>

To get the snow to show, all you have to do is call the makeItSnow function at the bottom of your JavaScript file.

makeItSnow();

If you are interested in learning more about how the snow animation works, feel free to check out the original source on Codepen.

Now we can see the beautiful snow falling down in Chicago! 

holiday

 

Wrapping things up...

At this point, we've learned how to create a holiday map with two different tools: XYZ Studio and Tangram.

XYZ Studio is a great tool for those with limited coding experience who quickly want to visualize data on a map and then share with friends and family.

For those with a little bit more technical experience, Tangram is a great tool for creating rich, highly-customizable, and interactive web mapping experiences.

On top of that, we've learned that maps can be a great tool for display all sorts of data; in this case, we've displayed location data of volunteer opportunities for the Food Depository as an alternate way for potential volunteers to find nearby opportunities.

If you decide to create something cool, feel free to give us a shout on Twitter at @dbabbs or @heredev. We love seeing what you all build with maps 🌍 and HERE APIs.

Happy Holidays!