Create an Interactive Map of Tokyo with JavaScript

Published: June 17, 2024

Create an Interactive Map of Tokyo with JavaScript

Background

Most apps nowadays have interactive SVG maps which let you interact with elements in the map by either clicking or hovering on them.

It's crucial to know how to build such an interactive map with simple tools such as SVG and JavaScript in order to be a fully-fledged web developer.

Objective

In this blog, we will use an SVG map of Tokyo where some information will be displayed when you hover over a municipality in the city.

You can apply the code developed in this code to any kind of SVG map. It doesn't have to be Tokyo at all.

I have chosen Tokyo beacuse I was able to find its municipal SVG map, as well some random data that I could display when you hover over the municipality.

I will be mainly using JavaScript and a little bit of Svelte in this code. Svelte is chosen for ease of use, but its syntax can be easily changed back to plain vanilla JavaScript.

No libraries are imported for the tooltip function we use to display info when a municipality is hovered.

Method

SVG File

We start with a SVG map of Tokyo. Here is the map I have created using various sources on the internet. It's a no-fills svg file that is only 13 KB. It provides the geometry of municipalities as well as its name and municipality code:

SVG File

Below you can see the actual SVG.

The 23 special wards are colored in blueviolet while other municipalities are colored in steelblue My 2 favorite colors :)

Having name and code assigned to each municipality allows us to identify whicih municipality mouse is hovered over.

You can find the SVG file here.

Supplemental Data

Now that we have the SVG file, we need some data to show when the user hovers over the municipality. For this, I have used the population and household data provided by the Bureau of Statistics. The data looks like this:

Population data

Showing only numbers is boring. So I decided to spice up things by adding a picture to each municipality. The pictures are fetched from Wikipedia (Scroll to see all).

千代田区

千代田区

中央区

中央区

港区

港区

新宿区

新宿区

文京区

文京区

台東区

台東区

墨田区

墨田区

江東区

江東区

品川区

品川区

目黒区

目黒区

大田区

大田区

世田谷区

世田谷区

渋谷区

渋谷区

中野区

中野区

杉並区

杉並区

豊島区

豊島区

北区

北区

荒川区

荒川区

板橋区

板橋区

練馬区

練馬区

足立区

足立区

葛飾区

葛飾区

江戸川区

江戸川区

八王子市

八王子市

立川市

立川市

武蔵野市

武蔵野市

三鷹市

三鷹市

青梅市

青梅市

府中市

府中市

昭島市

昭島市

調布市

調布市

町田市

町田市

小金井市

小金井市

小平市

小平市

日野市

日野市

東村山市

東村山市

国分寺市

国分寺市

国立市

国立市

福生市

福生市

狛江市

狛江市

東大和市

東大和市

清瀬市

清瀬市

東久留米市

東久留米市

武蔵村山市

武蔵村山市

多摩市

多摩市

稲城市

稲城市

羽村市

羽村市

あきる野市

あきる野市

西東京市

西東京市

西多摩郡瑞穂町

西多摩郡瑞穂町

西多摩郡日の出町

西多摩郡日の出町

西多摩郡檜原村

西多摩郡檜原村

西多摩郡奥多摩町

西多摩郡奥多摩町

大島町

大島町

利島村

利島村

新島村

新島村

神津島村

神津島村

三宅島三宅村

三宅島三宅村

御蔵島村

御蔵島村

八丈島八丈町

八丈島八丈町

青ヶ島村

青ヶ島村

小笠原村

小笠原村

I really like this view of pictures because as you scroll down you can see how Tokyo progressively moves from urban to rural and finally to islands.

It is refreshing to know that Tokyo is not just made up of 23 highly urban wards.

We mix the population data with pictures and we have a final JSON file that looks like this.

Final JSON file

Front End - SVG

Now that we have the SVG map where each path denotes a municipality. Let's add a function so that when the path is hovered, it will trigger a function:

<script>
let data = [
	{
		code: 13102,
		name: '中央区',
		population: { m: 53336, f: 58124 },
		household: 64206,
		image: 'https://upload.wikimedia...'
	}, // ... 
]

function handleMouseover(key) {
	// Get the municipality that is hovered
	entity = data.filter((d) => d.code === key)[0];
}
</script>

<svg>
	<path
		on:mouseover={() => handleMouseover(13102)}
		d="m 636,223 7,5 8,1 9,-12 -2,-6 11,-8 -9,-8 -2,5 -17,-3 -11,13 v 7 z"
	/>
	<!-- ... -->
</svg>

Above function is attached to every path in the SVG file. With this, we can now keep tabs on which municipality the user is hovering on.

Front End - Info Panel

Now let's create an info panel that shows the info about that municipality that the user is hovering on.

I recommed using Tailwind as it makes styling really easy. Read my article about it here.

Below is the code we use for creating the info panel:

<div class="flex rounded-xl overflow-hidden shadow-xl mx-auto my-8">
	<img
		class="h-100 w-[150px] min-w-[150px] max-w-[150px] object-cover"
		src="https://upload.wikimedia..."
		alt="中央区"
	/>
	<div class="px-8 py-4 flex gap-2 flex-col bg-white">
		<p class="text-3xl font-bold text-center">中央区</p>
		<div>
			<p class="text-xs text-slate-500 font-bold text-center">Population</p>
			<p class="text-xl text-center">111,460</p>
		</div>
		<div>
			<p class="text-xs text-slate-500 font-bold text-center"># Households</p>
			<p class="text-xl text-center">64,206</p>
		</div>
	</div>
</div>

This code produces below nice-looking panel. This is what we are going to show when a municipality is hovered.

中央区

中央区

Population

111,460

# Households

64,206

Front End - Tooltip

Now that we have SVG and info panel ready, the only thing remaining is to show the info panel when a municipality is hovered on.

We also want to do this next to the mouse, in a "Tooltip" fashion.

Below code is used to implement Tooltip using vanilla JavaScript. The good thing about this code is that, we divide the screen into 4 quadrants, and depending on the quadrant where there mouse is, we calculate the position of tooltip.

This is to make sure that tooltip does not bleed over the screen. For example., if mouse is too close to the bottom, the tooltip will appear above the mouse. On the other hand, if it's too close to the top, the tooltip will appear below the mouse.

I will write a separate blogpost for this implementation so if you are interested, feel free to check my blogs later.

<script>
function handleMouseMove(event) {
	let x = event.clientX;
	let y = event.clientY;
	let rect = container.getBoundingClientRect();

	info.style.top = y < innerHeight / 2 ? y - rect.top + 10 + 'px' : '';
	info.style.bottom = y < innerHeight / 2 ? '' : rect.bottom - y + 10 + 'px';

	info.style.left = x < innerWidth / 2 ? x - rect.left + 10 + 'px' : '';
	info.style.right = x < innerWidth / 2 ? '' : rect.right - x + 10 + 'px';
}
</script>

<svelte:window
	bind:innerWidth
	bind:innerHeight
	on:mousemove={(e) => handleMouseMove(e)}
/>

Result

Now that we have implemented all the necessary steps, we can take a look at our creation.

Hover over below SVG to see an image of it, its population and # households:

Looks pretty with the sleek info panel and the tooltip, doesn't it?

Conclusion

In this blogpost, we have developed an interactive map for showing some demographic data using Svelte, SVG, JavaScript, and Tailwind.

In order to achieve this, we have created an SVG file of Tokyo, collected relevant info such as population and image, and finally developed front-end elements like tooltip and info panel.

This kind of functionality is commonly used in dashboards so it is good to know how to implement it for a front-end/ full stack engineer.

Any questions? Let me know below.

Until the next blog, happy hacking!

Leave comment

Comments

Check out other blog posts

Create A Simple and Dynamic Tooltip With Svelte and JavaScript

2024/06/19

Create A Simple and Dynamic Tooltip With Svelte and JavaScript

JavaScriptSvelteSimpleDynamicTooltipFront-end
How to Easily Fix Japanese Character Issue in Matplotlib

2024/06/14

How to Easily Fix Japanese Character Issue in Matplotlib

MatplotlibGraphChartPythonJapanese charactersIssueBug
Book Review | Talking to Strangers: What We Should Know about the People We Don't Know by Malcolm Gladwell

2024/06/13

Book Review | Talking to Strangers: What We Should Know about the People We Don't Know by Malcolm Gladwell

Book ReviewTalking to StrangersWhat We Should Know about the People We Don't KnowMalcolm Gladwell
Most Commonly Used 3,000 Kanjis in Japanese

2024/06/07

Most Commonly Used 3,000 Kanjis in Japanese

Most CommonKanji3000ListUsage FrequencyJapaneseJLPTLanguageStudyingWordsKanji ImportanceWord Prevalence
Replace With Regex Using VSCode

2024/06/07

Replace With Regex Using VSCode

VSCodeRegexFindReplaceConditional Replace
Do Not Use Readable Store in Svelte

2024/06/06

Do Not Use Readable Store in Svelte

SvelteReadableWritableState ManagementStoreSpeedMemoryFile Size
Increase Website Load Speed by Compressing Data with Gzip and Pako

2024/06/05

Increase Website Load Speed by Compressing Data with Gzip and Pako

GzipCompressionPakoWebsite Load SpeedSvelteKit
Find the Word the Mouse is Pointing to on a Webpage with JavaScript

2024/05/31

Find the Word the Mouse is Pointing to on a Webpage with JavaScript

JavascriptMousePointerHoverWeb Development
Create an Interactive Map with Svelte using SVG

2024/05/29

Create an Interactive Map with Svelte using SVG

SvelteSVGInteractive MapFront-end
Book Review | Originals: How Non-Conformists Move the World by Adam Grant & Sheryl Sandberg

2024/05/28

Book Review | Originals: How Non-Conformists Move the World by Adam Grant & Sheryl Sandberg

Book ReviewOriginalsAdam Grant & Sheryl SandbergHow Non-Conformists Move the World
How to Algorithmically Solve Sudoku Using Javascript

2024/05/27

How to Algorithmically Solve Sudoku Using Javascript

Solve SudokuAlgorithmJavaScriptProgramming
How I Increased Traffic to my Website by 10x in a Month

2024/05/26

How I Increased Traffic to my Website by 10x in a Month

Increase Website TrafficClicksImpressionsGoogle Search Console
Life is Like Cycling

2024/05/24

Life is Like Cycling

CyclingLifePhilosophySuccess
Generate a Complete Sudoku Grid with Backtracking Algorithm in JavaScript

2024/05/19

Generate a Complete Sudoku Grid with Backtracking Algorithm in JavaScript

SudokuComplete GridBacktracking AlgorithmJavaScript
Why Tailwind is Amazing and How It Makes Web Dev a Breeze

2024/05/16

Why Tailwind is Amazing and How It Makes Web Dev a Breeze

TailwindAmazingFront-endWeb Development
Generate Sitemap Automatically with Git Hooks Using Python

2024/05/15

Generate Sitemap Automatically with Git Hooks Using Python

Git HooksPythonSitemapSvelteKit
Book Review | Range: Why Generalists Triumph in a Specialized World by David Epstein

2024/05/14

Book Review | Range: Why Generalists Triumph in a Specialized World by David Epstein

Book ReviewRangeDavid EpsteinWhy Generalists Triumph in a Specialized World
What is Svelte and SvelteKit?

2024/05/13

What is Svelte and SvelteKit?

SvelteSvelteKitFront-endVite
Internationalization with SvelteKit (Multiple Language Support)

2024/05/12

Internationalization with SvelteKit (Multiple Language Support)

InternationalizationI18NSvelteKitLanguage Support
Reduce Svelte Deploy Time With Caching

2024/05/11

Reduce Svelte Deploy Time With Caching

SvelteEnhanced ImageCachingDeploy Time
Lazy Load Content With Svelte and Intersection Oberver

2024/05/10

Lazy Load Content With Svelte and Intersection Oberver

Lazy LoadingWebsite Speed OptimizationSvelteIntersection Observer
Find the Optimal Stock Portfolio with a Genetic Algorithm

2024/05/10

Find the Optimal Stock Portfolio with a Genetic Algorithm

Stock marketPortfolio OptimizationGenetic AlgorithmPython
Convert ShapeFile To SVG With Python

2024/05/09

Convert ShapeFile To SVG With Python

ShapeFileSVGPythonGeoJSON
Reactivity In Svelte: Variables, Binding, and Key Function

2024/05/08

Reactivity In Svelte: Variables, Binding, and Key Function

SvelteReactivityBindingKey Function
Book Review | The Art Of War by Sun Tzu

2024/05/07

Book Review | The Art Of War by Sun Tzu

Book ReviewThe Art Of WarSun TzuThomas Cleary
Specialists Are Dead. Long Live Generalists!

2024/05/06

Specialists Are Dead. Long Live Generalists!

SpecialistGeneralistParadigm ShiftSoftware Engineering
Analyze Voter Behavior in Turkish Elections with Python

2024/05/03

Analyze Voter Behavior in Turkish Elections with Python

TurkeyAge Analysis2018 ElectionsVoter Behavior
Create Turkish Voter Profile Database With Web Scraping

2024/05/01

Create Turkish Voter Profile Database With Web Scraping

PythonSeleniumWeb ScrapingTurkish Elections
Make Infinite Scroll With Svelte and Tailwind

2024/04/30

Make Infinite Scroll With Svelte and Tailwind

SvelteTailwindInfinite ScrollFront-end
How I Reached Japanese Proficiency In Under A Year

2024/04/29

How I Reached Japanese Proficiency In Under A Year

JapaneseProficiencyJLPTBusiness
Use-ready Website Template With Svelte and Tailwind

2024/04/25

Use-ready Website Template With Svelte and Tailwind

Website TemplateFront-endSvelteTailwind
Lazy Engineers Make Lousy Products

2024/01/29

Lazy Engineers Make Lousy Products

Lazy engineerLousy productStarbucksSBI
On Greatness

2024/01/28

On Greatness

GreatnessMeaning of lifeSatisfactory lifePurpose
Converting PDF to PNG on a MacBook

2024/01/28

Converting PDF to PNG on a MacBook

PDFPNGMacBookAutomator
Recapping 2023: Compilation of 24 books read

2023/12/31

Recapping 2023: Compilation of 24 books read

BooksReading2023Reflections
Create a Photo Collage with Python PIL

2023/12/30

Create a Photo Collage with Python PIL

PythonPILImage ProcessingCollage
Detect Device & Browser of Visitors to Your Website

2024/01/09

Detect Device & Browser of Visitors to Your Website

JavascriptDevice DetectionBrowser DetectionWebsite Analytics
Anatomy of a ChatGPT Response

2024/01/19

Anatomy of a ChatGPT Response

ChatGPTLarge Language ModelMachine LearningGenerative AI