Following Mexico’s Journey in the 2018 FIFA World Cup using Mapbox

Riding the waves of this year’s World Cup, Mapbox setup an online competition to showcase our favorite team’s story using maps. Having used Mapbox to build a few interactive maps for work, I thought this would be a great opportunity to let loose and build something different.

I started off building a style for the map using Cartogram, an amazing tool by Mapbox that pulls color schemes from images to create custom map styles in seconds. Crazy right?

From there I took my new Mapbox style into Studio and refined the theme to better fit the data that I would be displaying. After a few rounds, some additional data layers (bathymetry, country/sovereign polygons, and names), and a lot of hex code pushing, I polished off the design of the map and got it setup into my html document.

For this project I wanted to create a slideshow of Mexico’s matches using a dual map setup so users could quickly go through each match and see a side-by-side comparison of each team’s geographic location. Using Foundation Sites to build the framework of the site, in combination with Luke Haas Scrollify jQuery plugin, I was able to choreograph the slides and scrolling of the site’s content with the map using a switch to turn on-and-off the different map layers as well as positions. Using this in sync with Scrollify’s $.scrollify.next()and $.scrollify.previous() functions I was able to combine each slide with it’s corresponding home and away countries.

function setActiveChapter(chapterName) {
if (chapterName === activeChapterName) return;
switch (chapterName) {
case 'hero':
home.setLayoutProperty('LAYER-NAME-STROKE', 'visibility', 'none');
home.setLayoutProperty('LAYER-NAME-FILL', 'visibility', 'none');
home.setLayoutProperty('LAYER-NAME-EXTRUDE', 'visibility', 'none');
home.setPaintProperty('country-extrude-germany', 'fill-extrusion-height', 150000);
home.setPaintProperty('country-extrude-mexico', 'fill-extrusion-height', 150000);
away.flyTo({
bearing: 180,
center: [123.4811, -7.1054],
pitch: 0,
zoom: 2.308
})
break;
case 'one': // Germany vs Mexico
home.setLayoutProperty('LAYER-NAME-STROKE', 'visibility', 'none');
home.setLayoutProperty('LAYER-NAME-FILL', 'visibility', 'none');
home.setLayoutProperty('LAYER-NAME-EXTRUDE', 'visibility', 'none');
home.setPaintProperty('country-extrude-south-korea', 'fill-extrusion-height', 200000);
away.setPaintProperty('country-extrude-mexico', 'fill-extrusion-height', 400000);
home.setPaintProperty('country-extrude-south-korea', 'fill-extrusion-height', 150000);
away.flyTo({
bearing: 0,
center: [-105, 23.4],
pitch: 24,
duration: 2800,
zoom: 4.825
});
break;
case 'two': // Korea vs Mexico
home.setLayoutProperty('LAYER-NAME-STROKE', 'visibility', 'none');
home.setLayoutProperty('LAYER-NAME-FILL', 'visibility', 'none');
home.setLayoutProperty('LAYER-NAME-EXTRUDE', 'visibility', 'none');
home.setPaintProperty('country-extrude-south-korea', 'fill-extrusion-height', 200000);
away.setPaintProperty('country-extrude-mexico', 'fill-extrusion-height', 400000);
home.setPaintProperty('country-extrude-germany', 'fill-extrusion-height', 150000);
home.setPaintProperty('country-extrude-sweden', 'fill-extrusion-height', 150000);
away.flyTo({
bearing: -67,
center: [-102, 23.4996828],
pitch: 56,
duration: 2800,
zoom: 3.825
});
break;
...
}

Here’s the init script for Scrollify and Mapbox:

function initMap(){
   // Add Loading Animation
homeMapContainer.addClass('is-loading');
awayMapContainer.addClass('is-loading');
   // Disable/Enable Interactions
home.scrollZoom.disable();
home.touchZoomRotate.disableRotation();
home.dragPan.enable();
home.doubleClickZoom.enable();
home.on('load', function() {
homeMapContainer.removeClass('is-loading');
});

away.scrollZoom.disable();
away.touchZoomRotate.disableRotation();
away.dragPan.enable();
away.doubleClickZoom.enable();
   away.on('load', function() {
awayMapContainer.removeClass('is-loading');
});
});
$(function() {
$.scrollify({
section: '.is-section',
easing:"easeInOutQuad",
scrollSpeed:1400,
scrollbars:false,
sectionName:false,
setHeights:false,
updateHash: false,
overflowScroll:false,
before:function(i) {
var activeSlide = $(".is-slide.is-active");
activeSlide.addClass("remove");
$("[data-slide=" + i + "]").addClass("is-active");
activeSlide.removeClass("remove is-active");
         var activeSection = $('.is-section.is-active');
activeSection.addClass('remove');
$("[data-section=" + i + "]").addClass("is-active");
activeSection.removeClass('remove is-active');
},
afterRender() {
$.scrollify.update();
$("[data-slide=0]").addClass("is-active");
$("[data-section=0]").addClass("is-active");
}
})
})

After finalizing the content and the choreography, I optimized the layout I originally built to work responsively on mobile and desktop. Try resizing the browser and you’ll see the the map switch from a horizontal split to a vertical split.

You can also click on the vector maps of each country for an example of Mapbox’s flyTo({}) function.

<button onClick="flyToFlag_de()" class="fly-to-button">
<img src="link/to/my/image.svg" class="team" alt="Team Flag" />
</button>
<script>
...
function flyToFlag_de() {
home.flyTo({
bearing: 0,
center: [9.925, 50.75],
pitch: 24,
speed: 0.25,
zoom: 5
});
home.setLayoutProperty('LAYER-NAME-STROKE', 'visibility', 'none');
home.setLayoutProperty('LAYER-NAME-FILL', 'visibility', 'none');
home.setLayoutProperty('LAYER-NAME-EXTRUDE', 'visibility', 'none');
}
...
</script>
First slide and dual map layout on tablets. Shoutout to Rishad Amarkhel for creating this cool FIFA 2018 World Map Cup graphic!
Knockout Match between Brazil and Mexico on Mobile.
Wide screen view of Match Two, Mexico vs South Korea.

Check out the live site at worldmapcup.youngbergdesign.com