d3 / d3-tile

Compute the quadtree tiles to display in a rectangular viewport.

Home Page:https://observablehq.com/collection/@d3/d3-tile

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Easier tile positioning?

curran opened this issue · comments

Currently, it is a bit cumbersome to set the scale and translate on the tile image container.

raster.attr("transform", "scale(" + tiles.scale + ")translate(" + tiles.translate + ")");

It can be particularly confusing because the scale must come first, which is not that common. It would be nice to be able to say this instead:

raster.attr("transform", tiles.transform);

Here's a prototype implementation of this where setting the transform property on the returned tiles array looks like this:

tiles.transform = d3.zoomIdentity
  .scale(k)
  .translate(x / k, y / k);

Without a dependency on d3-zoom, setting transform could look like this:

tiles.transform = {
  k: k,
  x: x,
  y: y,
  toString: function() {
    return "translate(" + this.x + "," + this.y + ") scale(" + this.k + ")";
  }
};

Duplicating toString from d3-zoom.

Here's an example that tests that this code is correct.

The implementation could also look like this, a mini d3-zoom transform:

function Transform(k, x, y) {
  this.k = k;
  this.x = x;
  this.y = y;
}

Transform.prototype = {
   toString: function() {
    return "translate(" + this.x + "," + this.y + ") scale(" + this.k + ")";
  }
};
...
/// inside tile(t)
tiles.transform = new Transform(k, x, y);

Here's an example that shows this approach working.

It might be interesting to consider splitting out Transform from d3-zoom as a micro-module, say d3-transform, so it would become sensible to add a dependency on only that piece rather than all of d3-zoom (and its transitive dependencies d3-drag, d3-selection, d3-transition).

I noticed this snippet in some of the updated examples, maybe ideas from it could be added into the library.

  • providing tiles.transform with scale / 256, intended for direct use with 256 X 256 image elements.
  • The rounding logic for crisp tile boundaries (at least I think that's what that is for..).
function stringify(scale, translate) {
  var k = scale / 256, r = scale % 1 ? Number : Math.round;
  return "translate(" + r(translate[0] * scale) + "," + r(translate[1] * scale) + ") scale(" + k + ")";
}

A similar comment, three years later: #53 (comment)

Adding this issue to 1.0 to see if we can figure out something more convenient.

I’m going to punt on this for 1.0 because I don’t have a great idea for making this easier. The main challenge is that there are many valid ways of rendering tiles, and most of the convenience methods would have to assume a particular rendering method (such as Canvas, or an SVG G with a transform), and I don’t want this library to be overly prescriptive in terms of rendering strategy.