
High Performance Map Interactions Using HTML5 Canvas - efkv
http://chairnerd.seatgeek.com/high-performance-map-interactions-using-html5-canvas/
======
rraval
This is an awesome writeup!

I was playing with the demo linked elsewhere in this thread [demo], and
noticed a bit of a hiccup when scrolling past multiple zoom levels. It seems
like there'd be a bit of a pause as the tiles were rendered at each successive
zoom level. It may be worthwhile to debounce the scroll event listeners with a
small timeout, so you can catch multiple successive scroll events and zoom
straight to the target zoom level without having to render each step along the
way.

Quick video of the stuttering:
[http://gfycat.com/BrilliantActiveAfghanhound](http://gfycat.com/BrilliantActiveAfghanhound)

[demo] [https://seatgeek.com/senators-at-flyers-
tickets/4-11-2015-ph...](https://seatgeek.com/senators-at-flyers-
tickets/4-11-2015-philadelphia-pennsylvania-wells-fargo-center/nhl/2220894/)

~~~
efkv
Thanks!

This has been an issue we have struggled with for a while. What you are
suggesting is basically how Leaflet typically handles scroll events. The
issue, however, primarily lies with the Apple trackpad. Basically the Apple
trackpad "fakes" inertial scrolling. When using the base Leaflet
implementation, we would zoom straight to the target zoom level (great), but
then the tail end of the intertial zoom would force it to zoom once more
(bad).

For a normal map of the world that has like 20 or 30 zoom levels, accidentally
missing the target zoom by a level does not matter too much. However, on our
maps, with only a couple zoom levels, missing your target zoom level really
hinders usability. Therefore we debounce the scroll events to keep zooming to
a level at a time. So its not a matter of tile rendering blocking zoom, but
rather a purposeful, if imperfect, decision.

This is by no means the right solution and we are keeping our eyes on the new
Leaflet release that may help solve this. Great catch, btw.

If you are really interested, here is a thread on exactly this issue:
[https://github.com/Leaflet/Leaflet/issues/2154](https://github.com/Leaflet/Leaflet/issues/2154)

~~~
rraval
Thanks for the thread. I figured mapping continuous input to discrete levels
was more difficult than I was making it seem (especially with the fragmented
way the web presents these devices).

~~~
efkv
No problem. It wouldn't be fun if it were easy!

------
piyush_soni
@Developers, I'm sorry if I missed it in the article, but can I see the online
demo somewhere? I went to your website and maps but still couldn't get to it.
Thanks.

~~~
dallasgutauckis
[https://seatgeek.com/senators-at-flyers-
tickets/4-11-2015-ph...](https://seatgeek.com/senators-at-flyers-
tickets/4-11-2015-philadelphia-pennsylvania-wells-fargo-center/nhl/2220894/)

~~~
diydsp
Tiles are good and responsive, but you may want to add a shadow behind the
text "Section N, Row M" because some arena pictures are largely white!

~~~
efkv
Any chance we could get a screenshot of where you are seeing this? Or at least
a venue/section? Thanks!

------
csytan
Great write up! I've been working with maps lately and this was a very
interesting read.

I've tried the Leaflet SVG layer and it can become quite slow when loaded with
thousands of points.

Another approach would be to use a custom SVG layer overlay using CSS
Transforms. I've used an SVG overlay with D3 and it was much faster at panning
and zooming. It could handle ~30k points (and lots of lines) without a problem
on my laptop.

Edit + an example:
[http://i.imgur.com/ey8YDWJ.jpg](http://i.imgur.com/ey8YDWJ.jpg)

------
pak
Canvas tiles are exactly the approach we took in making the ChromoZoom genome
browser, where we wanted people to smoothly zoom in on client drawn data at
60fps through 10 orders of magnitude:
[http://chromozoom.org](http://chromozoom.org) (Note that it's only used for
user provided data, as the default tracks are prerendered, like Google maps
v1.)

I highly recommend this hybrid approach of 10-20 canvases plus a sprinkling of
HTML elements for anybody looking to maximize responsiveness in this type of
UI. In our tests, SVG and HTML start stuttering in draggable layers around
tens of thousands of elements (easier to hit than you'd think). We actually
decided to do mouseover calculations ourselves, in a pixel map within a
mousemove handler, since having separate elements to trigger the mouseover was
too expensive.

------
undershirt
Really great to have a case study like this for knowing when to use SVG/DOM or
Canvas.

I knew that Canvas can easily be redrawn 60fps for things like games (though
it may overheat your laptop). Didn't know about using them as shiftable tiles
though. What a great way to minimize redraw! Is this how most online maps
work?

~~~
efkv
Tiling is a very common technique for online maps. Image tiles used to be the
standard, but there has been a lot of progress made with vector tiles (what
the new Google Maps uses), mainly due to the huge improvements in browser
performance as well as greater support of WebGL . Take a look at Mapbox GL, a
very cool vector tile renderer:

[https://www.mapbox.com/blog/mapbox-gl-
js/](https://www.mapbox.com/blog/mapbox-gl-js/)

------
coderzach
This is awesome, thanks for sharing!

One question, on your previous version you had a ton of big purple timeline
bars. Were those mostly "recalculate styles" or "update layer trees"? I'm
having similar issues and I'm wondering if canvas may be a better decision
than DOM.

~~~
efkv
I am quite certain there was a mix of both, but I honestly cannot remember the
details of the timeline. Basically, if your bottleneck is moving lots of DOM
elements around, then clustering is a good next step (depending on your use
case). If not, then canvas tiles have worked very well for us.

------
Zardoz84
Tardis TimeLine uses a pure brute DOM approach to create timelines. Seeing
this and how Vis.js does something similar, drives me to re-implement it
removing and adding the time flags. I can't afford to use canvas and it must
work on IE 8.

------
huskyr
Bit off-topic, but do any of the readers of this topic know of a good
combination of an open source (backend) tile server and a (frontend) JS
zooming library for dealing with large high-resolution images, of say,
something like old paintings?

~~~
hobbes78
Like this?

[http://www.thekremercollection.com/art/artists/Pieter-
Codde/...](http://www.thekremercollection.com/art/artists/Pieter-Codde/The-
sacrifice-of-Polyxena/detail/)

It's actually based on Google Maps API, which isn't open source, but
OpenLayers has equivalent functionality though I find it less fluid and
slower...

~~~
hobbes78
Oh, and regarding server side software, a web server is enough if you named
the tiles in a logic way. You'll have to provide a callback to OpenLayers to
return the name of the tile, similar to this pseudo-code:

GetTileFileName(zoom, x, y) {

    
    
        return "/MonaLisa/tiles/z" + zoom + "lon" + x + "lat" + y + ".png";
    
    }

------
albertoleal
Are canvas tiles more performant than one giant canvas sized to fit within a
user's browser?

~~~
efkv
So basically what we wanted to avoid was doing lots of redrawing during
panning. If there were a single static canvas with the image tiles moving
underneath it, then it would have to constantly redraw during panning. By
using tiles, you only have to draw or redraw as necessary, e.g. as you pan to
a part of the map outside of the current bounds.

------
dmix
This is great. I use Seatgeek 100% because of their excellent design work.

------
shirman
Maybe someone know wayfinding on HTML5?

