d3 / d3-plugins

[DEPRECATED] A repository for sharing D3.js V3 plugins.
https://github.com/d3/d3/wiki/Plugins
Other
1.81k stars 684 forks source link

Flickering in d3.geo.tile #148

Closed kachkaev closed 8 years ago

kachkaev commented 8 years ago

I just posted a related question on Stack Overflow and decided to raise the issue here too.

How would it be possible to avoid flickering of tiles when d3.geo.tile is zoomed and panned? The effect makes the UX a bit poor. Demo: http://bl.ocks.org/mbostock/5342063

kachkaev commented 8 years ago

Partial solution: make tile url less random (at least less flickering occurs when certain zoom/pan is revisited)

// before
image.enter().append("image")
      .attr("xlink:href", function(d) { return "http://" + ["a", "b", "c"][Math.random() * 3 | 0] + ".tile.openstreetmap.org/" + d[2] + "/" + d[0] + "/" + d[1] + ".png"; })

// after
image.enter().append("image")
      .attr("xlink:href", function(d) { return "http://" + ["a", "b", "c"][ (d[0] + d[1] + d[2]) % 3 ] + ".tile.openstreetmap.org/" + d[2] + "/" + d[0] + "/" + d[1] + ".png"; })
mbostock commented 8 years ago

This is not an issue with d3.geo.tile per se but a limitation of the example. The problem is that the tiles are removed immediately when they are no longer needed (e.g., when the nearest integer zoom level changes), rather than waiting until the new tiles that will replace them have loaded. One way to avoid flickering is to listen to the new tiles being loaded, and when new tiles completely cover an old tile, remove the old tile. This is outside the scope of d3.geo.tile, which simply computes which tiles are visible in a given viewport, and nothing else.

kachkaev commented 8 years ago

@mbostock waiting for new tiles to load would be an ideal scenario, but it's probably quite difficult to implement (consider a tile split into 4 other tiles 3 out of which are already loaded and one is still on its way). Just a delay of 0.5-1s before a tile is removed can solve 90% of flickering cases. This would improve a lot of visualisations that are built on top of your example.

Even if you think that de-flickering is outside of the team's interest, please at least consider replacing Math.random() in the tile url. See above + demo.

Cheers!