Using a Service Worker to generate diagnostic XYZ tiles

Photo by Kelly Sikkema on Unsplash

Sometimes you’re developing a typical tile-based web map thing and need to sanity-check your vectors or imagery or whatevers.

In this situation, you might visually compare it to other vectors or imagery in your map. But what if you don’t have anything to compare to?

In this article, I present a quick-n-dirty “fake XYZ tile server” that you can drop into any web app, and use it to feed descriptive tiles to your map.

It looks like this:

I live in 26, 19, 5 and we hate (HATE) those guys in 27, 19, 5.

Live action demo

The image above is from the example website here:

https://fake-xyz-tile-sw.joelmalone.com.au/

And the source code is available here:

https://github.com/joelmalone/fake-xyz-tile-sw.js

Yeh but why

The “fake XYZ tile server” is useful because:

  • It will generate tile images that display the rendered X, Y and Z of the tile that was requested. Useful for debugging!
  • It’s completely client-side. It’s just a service worker, so you can drop it into any web app.
  • It doesn’t have any external dependencies.
  • It can be consumed by any tile-based web map framework that supports URLs.
  • It’s simple; you can easily tweak it to suit your needs.

This is what it looks like in action, with an OSM base map behind it to provide some context:

Fake XYZ tiles can be overlaid onto another layer, providing diagnostic context for both.

You could use this information to diagnose issues with your custom imagery or vector layers.

It’s even useful for continuing to work while offline, without a connection to your usual base map servers.

Yeh but how

The source code is reasonably simple, and easy to adapt. Simply drop this as a new .js file (e.g. serve-tiles-sw.js) into your web app:

/* serve-tiles-sw.js */function onFetch(event) {
const url = new URL(event.request.url)
if (url.host === 'fake-server') {
event.respondWith(
generateImage(url)
);
break;
}
}
async function generateImage(url) {
const [, x, y, z] = url.pathname
.split('/')
.map(i => Number.parseInt(i))
const canvas = new OffscreenCanvas(256, 256);
var context = canvas.getContext("2d");
context.fillStyle = 'orange';
context.fillRect(8, 8, 240, 240);
context.font = "20px Arial";
context.fillStyle = 'black';
context.fillText(`${x}, ${y}, ${z}`, 16, 128);
const blob = await canvas.convertToBlob() return new Response(blob)
}
self.addEventListener("fetch", onFetch);

And then call this (e.g. from index.html) to register the service worker:

navigator.serviceWorker.register(‘serve-tiles-sw.js’)

And then add a new XYZ layer to your map, using this as the URL, and adapting it as necessary to suit your map framework:

https://fake-server/{x}/{y}/{z}

Gotcha: WebKit doesn’t support OffscreenCanvas (or “oh right, I forgot we were doing web development”)

OffscreenCanvas is not supported on Safari iOS (nor Safari anywhere), as can be seen in the Browser Compatibility section for OffscreenCanvas on MDN:

C’mon Apple… c’monnnnnnnn

This means that the above code won’t work in the following browsers:

Development on OffscreenCanvas in WebKit seems to have stalled around a year ago, so it doesn’t look like we’ll see it implemented any time soon.

A straight-forward alternative to OffscreenCanvas would be to find a package on NPM that allows us to draw and encode images in a pure Javascript way. But uhhhh maybe I’ll do that another day.

--

--

--

Software Engineer living in Southwest Western Australia

Love podcasts or audiobooks? Learn on the go with our new app.

Recommended from Medium

How to Write a Cloud Function to Send SMS in Node.js and Plivo’s SMS API

Top 10 JavaScript Hacks That Every Developer Should Know

10 things people don’t tell you about Front End development

What’s new in Angular 7?

Getting Started with Lightning, the TV-App Development Framework

Build a Nav-bar with React & Node.js

Using the Youtube API to get live viewer count

React — StateFull and StateLess

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Joel Malone

Joel Malone

Software Engineer living in Southwest Western Australia

More from Medium

How to Convert Shapefiles to GeoJSON

Guidance of installing and usage of PostGIS on MacOS

Demystifying mAP 🧐

How to Add a Placemark Using Coordinates in Google Earth

Pin on the map