---
title: "Thematic Interactive Map"
description: Recreating a thematic Swiss map as an interactive highcharter visualization.
date: 2017-01-20
date-modified: 2026-08-13
categories: [maps, data-visualization, highcharter, minipost]
image: images/preview.gif
---
```{r setup, include=FALSE}
source(here::here("blog", "_R", "post_setup.R"))
install_missing_packages(c(
"tidyverse", "rmapshaper", "highcharter", "geojsonio", "viridis",
"sf"
))
```
The last month, yep, the past year I've working on create maps
easily with [highcharter](http://jkunst.com/highcharter/), so when I saw [this chart](https://timogrossenbacher.ch/2016/12/beautiful-thematic-maps-with-ggplot2-only/)
I took as challege!

> Challenge accepted. it's gonna be legen...
> -- <cite>Me.</cite>
## Packages and Data
The data used for this chart is the same using by Timo. But the workflow
was slightly modified:
1. Read the shapefile with `sf::st_read`.
2. Simplify the shapefile (optional step) using `rmapshaper::ms_simplify`.
3. Then transform the map data to geojson using `geojsonio::geojson_list`.
> **Migration note (2026).** The original post used `maptools`, which has since
> been retired from CRAN. This version reads the shapefile with the maintained
> `sf` package and keeps the rest of the original workflow intact.
```{r load-swiss-map-data}
library(tidyverse)
library(rmapshaper)
library(sf)
library(highcharter)
library(geojsonio)
library(viridis)
shape <- here::here(
"blog", "posts", "2017-01-05-thematic-interactive-map", "data", "gde-1-1-15.shp"
)
map <- sf::st_read(shape, quiet = TRUE)
map <- ms_simplify(map, keep = 1) # because ms_simplify fix the ü's
map <- geojson_list(map)
# this was to put the name on the tooltip
map$features <- map(map$features, function(x) {
x$properties$name <- x$properties[["Secondary_"]]
x
})
data <- read_csv(here::here(
"blog", "posts", "2017-01-05-thematic-interactive-map", "data", "avg_age_15.csv"
))
data <- select(data, -1)
data <- rename(data, value = avg_age_15)
# colors
no_classes <- 6
colors <- magma(no_classes + 2) %>%
rev() %>%
head(-1) %>%
tail(-1) %>%
gsub("FF$", "", .)
brks <- c(min(data$value), c(40,42,44,46,48), max(data$value))
brks <- ifelse(1:(no_classes + 1) < no_classes, floor(brks), ceiling(brks))
```
## Map
Create the raw map is straightforward. The _main_ challege was replicate the
relief feature of the orignal map. This took _some days_ to figure
how add the backgound image. I did almost lost the hope but you know, new year,
so I tried a little more and it was possible :):
1. First I searched a way to transform the tif image to geojson. I wrote
a mail [@frzambra](https://twitter.com/frzambra) a geoRexpert :D. and
he kindly said me that I was wrong. And he was right. NEXT!
2. I tried with use `divBackgroundImage` but with this the image use all the
container... so... NEXT.
3. Finally surfing in the web I met `plotBackgroundImage` argument in highcharts
which is uesd to put and image only in plot container (inside de axis) and
it works nicely. It was necessary hack the image using the `preserveAspectRatio`
(html world) to center the image but nothing magical.
```{r build-thematic-swiss-map}
#| column: page
urlimage <- "https://raw.githubusercontent.com/jbkunst/r-posts/master/061-beautiful-thematic-maps-with-ggplot2-highcharter-version
/02-relief-georef-clipped-resampled.jpg"
hc <- highchart(type = "map") %>%
# data part
hc_add_series(
mapData = map, data = data, type = "map",
joinBy = c("BFS_ID", "bfs_id"), value = "value",
borderWidth = 0
) %>%
hc_colorAxis(dataClasses = color_classes(brks, colors)) %>%
# functionality
hc_tooltip(
headerFormat = "",
pointFormat = "{point.name}: {point.value}",
valueDecimals = 2
) %>%
hc_legend(
align = "right",
verticalAlign = "bottom",
layout = "vertical",
floating = TRUE
) %>%
hc_mapNavigation(enabled = FALSE) %>% # if TRUE to zoom the relief image dont zoom.
# info
hc_title(text = "Switzerland's regional demographics") %>%
hc_subtitle(text = "Average age in Swiss municipalities, 2015") %>%
hc_credits(
enabled = TRUE,
text = "Map CC-BY-SA; Author: Joshua Kunst (@jbkunst) based mostly on Timo Grossenbacher (@grssnbchr) work, Geometries: ThemaKart, BFS; Data: BFS, 2016; Relief: swisstopo, 2016"
) %>%
# style
hc_chart(
plotBackgroundImage = urlimage,
backgroundColor = "transparent",
events = list(
load = JS("function(){ $(\"image\")[0].setAttribute('preserveAspectRatio', 'xMidYMid') }")
)
)
hc
```
> DARY! Legendary.
> -- <cite>Me.</cite>
Same as the original/ggplot2 version **but interactive**! I'm very happy with the result.
But anyway, there are some details:
1. The image/relief need to be accesible in web. I don't know how
to add images as dependencies yet. I tried econding the image but didn't work.
2. I could not do the legend same as the original. So I used `dataClasses`
instead of `stops` in `hc_colorAxis`.