GithubHelp home page GithubHelp logo

d3 / d3-tile Goto Github PK

View Code? Open in Web Editor NEW
120.0 12.0 28.0 195 KB

Compute the quadtree tiles to display in a rectangular viewport.

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

License: BSD 3-Clause "New" or "Revised" License

JavaScript 100.00%

d3-tile's Introduction

d3-tile

Quadtree tiles are common for representing large, multi-resolution geometry and images, as in “slippy” maps. d3.tile provides a convenient mechanism for computing which tile coordinates should be visible in the given viewport. Unlike dedicated libraries for slippy maps, such as Leaflet, d3.tile’s tiny, low-level API is agnostic about how the tiles are presented and offers greater flexibility. d3.tile works well with d3-geo for geographic maps and d3-zoom for interaction.

For examples, see the d3-tile collection on Observable.

Installing

If you use NPM, npm install d3-tile. Otherwise, download the latest release. You can also load directly as a standalone library. ES modules, AMD, CommonJS, and vanilla environments are supported. In vanilla, a d3 global is exported:

<script src="https://cdn.jsdelivr.net/npm/d3-tile@1"></script>
<script>

const tile = d3.tile();
const tiles = tile({k: 256, x: 480, y: 250});

</script>

API Reference

# d3.tile() · Source, Examples

Constructs a new tile layout with the default settings.

const tile = d3.tile();

# tile(…arguments) · Source, Examples

Computes the set of tiles to display given the current settings, computing the scale and translate by invoking the corresponding accessors with the given arguments. Returns an array of [x, y, z] arrays representing the x- (horizontal), y- (vertical) and z- (zoom) integer coordinates of any tiles which intersect the current viewport; these are the “visible” tiles. The returned tiles array also has tiles.scale and tiles.translate properties which together with an individual tile’s x and y determine the intended location of the tile in the viewport.

For example, the following function computes the pixel coordinates of the top-left corner of the given tile in the current viewport:

function position(tile, tiles) {
  const [x, y] = tile;
  const {translate: [tx, ty], scale: k} = tiles;
  return [(x + tx) * k, (y + ty) * k];
}

And in use:

const tile = d3.tile();
const tiles = tile({k: 256, x: 480, y: 250});
for (const t of tiles) {
  console.log(`tile ${t} is at ${position(t, tiles)}`);
}

See Zoomable Tiles for more information on tile coordinates.

# tile.extent([extent]) · Source

If extent is specified, sets this tile layout’s viewport extent to the specified array [[x0, y0], [x1, y1]], where [x0, y0] is the top-left corner and [x1, y1] is the bottom-right corner, and returns this tile layout. If extent is not specified, returns the current viewport extent, which defaults to [[0, 0], [960, 500]].

const tile = d3.tile().extent([[100, 200], [300, 400]]);

Setting the viewport extent implicitly sets the viewport size.

# tile.size([size]) · Source

If size is specified, sets this tile layout’s viewport size to the specified array of numbers [width, height] and returns this tile layout. If size is not specified, returns the current viewport size, which defaults to [960, 500].

const tile = d3.tile().size([200, 200]);

This is a convenience method for setting the viewport extent to [[0, 0], [width, height]].

# tile.scale([scale]) · Source

If scale is specified, sets this tile layout’s scale function and returns this tile layout. If scale is a function, it is invoked when the tile layout is invoked, being passed the same arguments as the tile layout; this function must return a number indicating the desired width and height of the world tile [0, 0, 0].

const tile = d3.tile().scale(t => t.scale).translate(t => t.translate);
const tiles = tile({scale: 1024, translate: [100, 200]});

If scale is not a function, it assumed to be a constant number, and is wrapped in a function.

const tile = d3.tile().scale(1024).translate([100, 200]);

If scale is not specified, returns the current layout scale function, which defaults to:

function scale(transform) {
  return transform.k;
}

This default is compatible with a d3-zoom transform.

# tile.translate([translate]) · Source

If translate is specified, sets this tile layout’s translate function and returns this tile layout. If translate is a function, it is invoked when the tile layout is invoked, being passed the same arguments as the tile layout; this function must return an array of numbers [x, y] indicating the desired coordinates the center of the world tile [0, 0, 0].

const tile = d3.tile().scale(t => t.scale).translate(t => t.translate);
const tiles = tile({scale: 1024, translate: [100, 200]});

If translate is not a function, it is assumed to be a constant array [x, y] and is wrapped in a function.

const tile = d3.tile().scale(1024).translate([100, 200]);

If translate is not specified, returns the current layout translate function, which defaults to:

function translate(transform) {
  return [transform.x, transform.y];
}

This default is compatible with a d3-zoom transform.

# tile.clampX([clamp]) · Source, Examples

If clamp is specified, sets whether or not the visible tiles will be clamped in the x-dimension and returns this tile layout. If clamp is not specified, returns whether x-clamping is enabled, which defaults to true. If x-clamping is disabled, then the tile layout may return tiles that are outside the normal bounds 0 ≤ x < 2^z of the “world” tile [0, 0, 0].

const tile = d3.tile().clampX(false);

See d3.tileWrap for converting these coordinates to wrapped in-world coordinates, and Wrapped Tiles for example.

# tile.clampY([clamp]) · Source

If clamp is specified, sets whether or not the visible tiles will be clamped in the y-dimension and returns this tile layout. If clamp is not specified, returns whether y-clamping is enabled, which defaults to true. If y-clamping is disabled, then the tile layout may return tiles that are outside the normal bounds 0 ≤ y < 2^z of the “world” tile [0, 0, 0].

const tile = d3.tile().clampY(false);

See d3.tileWrap for converting these coordinates to wrapped in-world coordinates, and Wrapped Tiles for example. See also tile.clampX.

# tile.clamp([clamp]) · Source

If clamp is specified, sets tile.clampX and tile.clampY to the specified boolean clamp and returns this tile layout. If clamp is not specified, returns true if tile.clampX and tile.clampY are both true, and false otherwise.

const tile = d3.tile().clamp(false);

# tile.tileSize([tileSize]) · Source, Examples

If tileSize is specified, sets this tile layout’s tile width and height to the specified number tileSize and returns this tile layout. If tileSize is not specified, returns the current layout tile size, which defaults to 256. 256 and 512 are the most common tile sizes.

const tile = d3.tile().tileSize(512);

# tile.zoomDelta([zoomDelta]) · Source, Examples

If zoomDelta is specified, sets this tile layout’s zoom offset to the specified number zoomDelta and returns this tile layout. If zoomDelta is not specified, returns the current zoom offset, which defaults to 0. The zoom offset affects which z-coordinate is chosen based on the current scale; the default zoom offset of 0 will choose the z that is closest the displayed size; a zoom offset of -1 will use z - 1, giving tiles that are twice as big (lower resolution); a zoom offset of +1 will use z + 1, giving tiles that are twice as small (higher resolution). The latter might be appropriate for showing 256×256 tiles in a 128×128 space on a high-resolution screen.

const tile = d3.tile().zoomDelta(2);

# d3.tileWrap(tile) · Source, Examples

Given tile coordinates [x, y, z], where x and y may be outside the “world” tile [0, 0, 0], returns the wrapped tile coordinates [x′, y′, z] where j = 2 ^ z, x′ = x - ⌊x / j⌋ * j and y′ = y - ⌊y / j⌋ * j. This function is most commonly used in conjunction with tile.clampX to allow horizontal wrapping of web Mercator tiles.

d3.tileWrap([-1, 0, 1]) // [1, 0, 1]
d3.tileWrap([-1, 0, 2]) // [3, 0, 2]

See Wrapped Tiles for example.

d3-tile's People

Contributors

clhenrick avatar curran avatar jfsiii avatar mbostock avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

d3-tile's Issues

1.0

This library is pretty solid and has not changed much in a year. Perhaps it's time to give it version 1.0.

@mbostock Do you agree?

Basic Image API

Create a basic API that wraps the image logic from existing examples.

Part of #3

Allowing wrapping in y, not just x.

The API for tile.wrap assumes you’d only ever want to wrap in x, but we should also allow wrapping in y (e.g., for transverse Mercator). In general, this library shouldn’t make any assumptions about geographic coordinates; it’s a planar tile quadtree.

I propose we remove tile.wrap and replace it with tile.wrapX and tile.wrapY for 1.0.

The tile size should be configurable.

It currently is limited to 256, which is a reasonable default, but any power of two square should be reasonable. (Instances of 8 in the code probably refer to Math.log2(tileSize).) In theory any width and height would also be possible but I think that generalization would make the code more complicated than necessary for now.

The function `wrap()` does not work as expected

The doc says that If wrap is specified, sets this tile layout’s wrapping option to the specified boolean value and returns this tile layout, however it does not work as expected. Do we have some tests or examples for the wrap() function?

Documentation *very* .... uhm generic, not to say meaningless ;)

What is 'scale', actually?

What is the unit of 'point'? Is it a pixel?

What are the units of 'size' and what is the difference to 'extent'?

Given the myriad of examples for obsolete versions out there, a precise documentation
might actually be helpful ....

Usage with `import`

I think the documentation should include usage instructions when importing d3 as an ES6 module:

import * as d3 from 'd3';

How is d3-tile to be imported?

Wonky d3-array injection

The build seems to be trying to inject d3-array (a dependency of d3-tile) in a strange way.

Currently, the first few lines of the built file look like this:

1. (function (global, factory) {
2.   typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('d3-array')) :
3.   typeof define === 'function' && define.amd ? define(['exports', 'd3-array'], factory) :
4.   (factory((global.d3 = global.d3 || {}),global.d3Array));
5. }(this, function (exports,d3Array) { 'use strict';

In the browser, this throws an error when trying to resolve global.d3Array.

To get this to work inside Raster & Vector 4.0, I ended up manually changing line 4 to be:

(factory((global.d3 = global.d3 || {}),global.d3));

This works fine. Any ideas on how to make the build generate this?

Generalized 2D transforms?

In the future, d3-zoom will likely support arbitrary 2D transforms (at the very least, rotate and non-uniform scaling, if not skew). We should think about how this might affect the d3-tile API. For one thing the logic will be more complex to determine which tiles are visible in the viewport, as the tiles will no longer be axis-aligned.

tile.transform

Currently, setting the scale and transform based on a zoom transform is a bit cumbersome:

var transform = d3.event.transform;
var tiles = tile
  .scale(transform.k)
  .translate([transform.x, transform.y])
  ();

It would be nice to be able to say this instead:

var transform = d3.event.transform;  
var tiles = tile.transform(transform)();

Here's a prototype implementation for this where the setter looks like this:

tile.transform = function(_) {
  if(arguments.length){
    return tile.scale(_.k).translate([_.x, _.y]);
  } else {
    return d3.zoomIdentity.translate(tx, ty).scale(scale);
  }
};

Image API

Copied from d3/d3-geo#35

There's room for building a higher level module on top of the existing tile code for working with images. Currently each of the examples re-implements image loading logic separately, along the lines of the following (from Raster & Vector II):

var raster = svg.append("g");
...
function zoomed() {
  ...
  var image = raster
      .attr("transform", "scale(" + tiles.scale + ")translate(" + tiles.translate + ")")
    .selectAll("image")
      .data(tiles, function(d) { return d; });

  image.exit()
      .remove();

  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"; })
      .attr("width", 1)
      .attr("height", 1)
      .attr("x", function(d) { return d[0]; })
      .attr("y", function(d) { return d[1]; });
}

I wonder if it might make sense to try to encapsulate this logic into an API similar to that of Leaflet. The API could take as input the raster g element and A URL pattern for tiles, and expose methods for setting the scale and translate. Examples of features that could be added into such a module include:

  • Tile URL template strings like 'http://{s}.tile.osm.org/{z}/{x}/{y}.png'. This would make it easy to use different tile providers based on declarative data, like in this Leaflet Providers Demo.
    • Caching tiles. As an example, Raster & Vector II has the behavior of re-loading the same tiles again and again, due to the randomness introduced in the URL generation. I think this issue would be solved by deterministic URL generation, leaving the actual caching up to the browser.
  • Showing larger, blurry tiles in the background as smaller tiles load in the foreground. This would vastly improve the user experience when zooming. The current behavior in the examples is that the larger tiles disappear, and the user is looking at empty white space until the higher zoom level tiles are loaded. This would however introduce complexity to the code. The exiting of tiles would be contingent upon all of their "child" tiles having loaded.

Have wrap images link to examples

The wrap images in the README are nice, but I feel like clicking on them should take me to a minimal example that produces that image.

Aspect ratios other than 1:1

In working on #22, I ran into another issue:

As far as I can tell (please correct me if I'm missing something), the code assumes that the world (or whatever the "universe" of the tile-map is) fits on one square tile when fully zoomed out (aspect ratio of 1:1). This assumption holds for most tile services out there, but I encountered a few that use a different projection, such that the minimum zoom level results in the world fitting on two side-by-side square tiles (aspect ratio of 2:1). This causes the tile.wrap method to wrap too soon.

Example:

The tile service here has an "aspect ratio" of 2:1:
https://services.arcgisonline.com/arcgis/rest/services/ESRI_Imagery_World_2D/MapServer

The following two tiles constitute a full world map:
https://services.arcgisonline.com/arcgis/rest/services/ESRI_Imagery_World_2D/MapServer/tile/0/0/0
https://services.arcgisonline.com/arcgis/rest/services/ESRI_Imagery_World_2D/MapServer/tile/0/0/1

My suggested solution would be to add a tile.aspectRatio method which would allow the user to specify an alternative ratio (default being 1:1 of course) like so:

var tiles = d3.tile()
    .aspectRatio({ x:2, y:1 })
    ();

Of course, in order to avoid needing to wrap in the middle of a tile, at least one of the x or y in the aspect ratio would have to be 1.

I can start working on an implementation of an aspectRatio method unless you object or have other thoughts.

Easier tile positioning?

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);

Some tiles do not render

I opened up a question on Stackoverflow about this, but figured it might be worth posting about on here in case it's an actual bug. It seems like using D3-tile with Openstreetmaps is leaving me with some tiles that never render unless zoom or position is adjusted.

Here are some relevant code blocks:

// init tiles for map rendering
var tile = d3Tile.tile()
                    .size([width, height]);

// init zoom
var zoom = d3.zoom()
                // allow for zooming in very close
                .scaleExtent([1 << 12, 1 << 24])
                .on('zoom', zoomed);
function zoomed() {
    var transform = d3.event.transform;

    // scale tiles
    var tiles = tile.scale(transform.k)
                    .translate([transform.x, transform.y])
                    ();
// update map images
    var image = g_raster.attr('transform', stringify(tiles.scale, tiles.translate))
                        .selectAll('image')
                        .data(tiles, function(d) {return d;});

    image.exit().remove();

    image.enter().append('image')
        .attr('xlink:href', function(d) {return 'http://' + 'abc' [d.y % 3] + '.tile.openstreetmap.org/' + d.z + '/' + d.x + '/' + d.y + '.png';})
        .attr('x', function(d) { return d.x * 256; })
        .attr('y', function(d) { return d.y * 256 })
        .attr('width', 256)
        .attr('height', 256);
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 + ')';
}

Investigate failing postpublish script

When I published v0.0.4, I saw the following error:

> [email protected] postpublish .
> VERSION=`node -e 'console.log(require("./package.json").version)'`; git push && git push --tags && cp build/d3-tile.js ../d3.github.com/d3-tile.v0.0.js && cp build/d3-tile.min.js ../d3.github.com/d3-tile.v0.0.min.js && cd ../d3.github.com && git add d3-tile.v0.0.js d3-tile.v0.0.min.js && git commit -m "d3-tile ${VERSION}" && git push && cd - && zip -j build/d3-tile.zip -- LICENSE README.md build/d3-tile.js build/d3-tile.min.js

Counting objects: 3, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 285 bytes | 0 bytes/s, done.
Total 3 (delta 2), reused 0 (delta 0)
remote: Resolving deltas: 100% (2/2), completed with 2 local objects.
To [email protected]:d3/d3-tile.git
   30c7c13..393a87c  master -> master
Counting objects: 1, done.
Writing objects: 100% (1/1), 156 bytes | 0 bytes/s, done.
Total 1 (delta 0), reused 0 (delta 0)
To [email protected]:d3/d3-tile.git
 * [new tag]         v0.0.4 -> v0.0.4
cp: cannot create regular file '../d3.github.com/d3-tile.v0.0.js': No such file or directory

npm ERR! Linux 4.4.0-62-generic
npm ERR! argv "/home/curran/.nvm/versions/node/v7.4.0/bin/node" "/home/curran/.nvm/versions/node/v7.4.0/bin/npm" "publish"
npm ERR! node v7.4.0
npm ERR! npm  v4.0.5
npm ERR! code ELIFECYCLE
npm ERR! [email protected] postpublish: `VERSION=`node -e 'console.log(require("./package.json").version)'`; git push && git push --tags && cp build/d3-tile.js ../d3.github.com/d3-tile.v0.0.js && cp build/d3-tile.min.js ../d3.github.com/d3-tile.v0.0.min.js && cd ../d3.github.com && git add d3-tile.v0.0.js d3-tile.v0.0.min.js && git commit -m "d3-tile ${VERSION}" && git push && cd - && zip -j build/d3-tile.zip -- LICENSE README.md build/d3-tile.js build/d3-tile.min.js`
npm ERR! Exit status 1
npm ERR! 
npm ERR! Failed at the [email protected] postpublish script 'VERSION=`node -e 'console.log(require("./package.json").version)'`; git push && git push --tags && cp build/d3-tile.js ../d3.github.com/d3-tile.v0.0.js && cp build/d3-tile.min.js ../d3.github.com/d3-tile.v0.0.min.js && cd ../d3.github.com && git add d3-tile.v0.0.js d3-tile.v0.0.min.js && git commit -m "d3-tile ${VERSION}" && git push && cd - && zip -j build/d3-tile.zip -- LICENSE README.md build/d3-tile.js build/d3-tile.min.js'.
npm ERR! Make sure you have the latest version of node.js and npm installed.
npm ERR! If you do, this is most likely a problem with the d3-tile package,
npm ERR! not with npm itself.
npm ERR! Tell the author that this fails on your system:
npm ERR!     VERSION=`node -e 'console.log(require("./package.json").version)'`; git push && git push --tags && cp build/d3-tile.js ../d3.github.com/d3-tile.v0.0.js && cp build/d3-tile.min.js ../d3.github.com/d3-tile.v0.0.min.js && cd ../d3.github.com && git add d3-tile.v0.0.js d3-tile.v0.0.min.js && git commit -m "d3-tile ${VERSION}" && git push && cd - && zip -j build/d3-tile.zip -- LICENSE README.md build/d3-tile.js build/d3-tile.min.js
npm ERR! You can get information on how to open an issue for this project with:
npm ERR!     npm bugs d3-tile
npm ERR! Or if that isn't available, you can get their info via:
npm ERR!     npm owner ls d3-tile
npm ERR! There is likely additional logging output above.

npm ERR! Please include the following file with any support request:
npm ERR!     /home/curran/repos/d3-tile/npm-debug.log

Will investigate.

URL Templates

This module could provide an API for working with URL template strings like 'http://{s}.tile.osm.org/{z}/{x}/{y}.png'. This would make it easy to use different tile providers based on declarative data, like in this Leaflet Providers Demo.

Such an API can help with the issue of caching tiles. As an example, Raster & Vector III has the behavior of re-loading the same tiles again and again, due to the randomness introduced in the URL generation. I think this issue would be solved by deterministic URL generation, leaving the actual caching up to the browser.

Leaflet has an implementation of this URL template logic. See Leaflet URL Template Docs.

Split out from #3.

v0.0.4 breaks examples in documentation that use v0.0.3

I noticed that the Unkpg CDN link in the README:

https://unpkg.com/[email protected]

is for v0.0.4, however the library used in the examples in the README,

//d3js.org/d3-tile.v0.0.min.js

is for v0.0.3 of the library.

If I attempt to use the v0.0.4 version, the examples break. Reading over the API docs for this library I was not able to yet debug why it is breaking them.

Tile helper function for tests.

I recommend creating a helper function like this:

function tile(x, y, z, tx, ty) {
  var d = [x, y, z];
  d.x = tx;
  d.y = ty;
  return d;
}

Then you can do:

test.deepEqual(tiles[0], tile(1, 5, 4, 256, 5 * 256));

And even better:

test.deepEqual(tiles, [
  tile(1, 5, 4, 1 * 256, 5 * 256),
  tile(2, 5, 4, 2 * 256, 5 * 256),
  tile(3, 5, 4, 3 * 256, 5 * 256),
  
]);

d3.event.transform has x and y NaN

Hello,

I opened the issue in d3-zoom but I think it's better here.

I'm trying to do something like this example:

http://bl.ocks.org/mbostock/5914438

using the current these version:
d3: 5.5.0
d3-tile: 0.0.4

and installing the packages with npm.
I have these imports:

import * as d3 from 'd3';
import * as d3Tile from "d3-tile";
import * as topojson from 'topojson';

When the data are loaded and the function zoomed is called, this part of code ha sa problem:

var transform = d3.event.transform;

transform.x and transform.y are 'NaN'

All the code is basically here. I only changed in the callback function for retrieving data from OSM the d parameter that is no more an array but an object.

stringify(scale: number, translate: Array): string
{
var k = scale / 256, r = scale % 1 ? Number : Math.round;
return "translate(" + r(translate[0] * scale) + "," + r(translate[1] * scale) + ") scale(" + k + ")";
}

zoomed()
{
var transform = d3.event.transform;

var tiles = this.tile
    .scale(transform.k)
    .translate([transform.x, transform.y])
    ();

this.vector
    .attr("transform", transform)
    .style("stroke-width", 1 / transform.k);

var image = this.raster
    .attr("transform", this.stringify(tiles.scale, tiles.translate))
  .selectAll("image")
  .data(tiles, function(d) { return d; });

image.exit().remove();

image.enter().append("image")
    .attr("xlink:href", function(d) { return "http://" + "abc"[d.x % 3] + ".tile.openstreetmap.org/" + d.z + "/" + d.x + "/" + d.y + ".png"; })
    .attr("x", function(d) { return d.x * 256; }) 
    .attr("y", function(d) { return d.y * 256; })
    .attr("width", 256)
    .attr("height", 256);

}

_initV()
{
const width = this.svgCanvas.clientWidth;
const height = this.svgCanvas.clientHeight;

const projection = d3.geoMercator()
    .scale(1 / (2*Math.PI))
    .translate([0, 0]);

var path = d3.geoPath()
    .projection(projection);

this.tile = d3Tile.tile()
    .size([width, height]);

var zoom = d3Zoom.zoom()
    .scaleExtent([1 << 11, 1 << 14])
    .on("zoom", this.zoomed);

this.svg = d3.select("svg")
    .attr("width", width)
    .attr("height", height);

this.raster = this.svg.append("g");

this.vector = this.svg.append("path");

fetch('http://localhost:8080/us.json').then(resp => {
        if (resp.ok)
            return resp.json();
        else {
            console.error(resp.statusText);
            throw new Error('Response error');
        }
    }).then(us => {
        var center = projection([-98.5, 39.5]);

        this.svg
            .call(zoom)
            .call(zoom.transform, d3.zoomIdentity
            .translate(width / 2, height / 2)
            .scale(1 << 12)
            .translate(-center[0], -center[1]));
        

        this.vector
            .attr("d", path(topojson.mesh(us, us.objects.counties)));
    }).catch(error => {
        console.error(error);
});

}

I tried the same code with a standalone html file and it works correctly. It doesn't if I use npm and the imports with webpack.

Many thanks.

Size should return (x1-x0, y1-y0) not (x1, y1)

I was going about building out the tests and I encountered this:

var tileLayout = d3.tile().extent([[100, 200], [300, 350]]);
test.deepEqual(tileLayout.size(), [200, 150]); // Currently fails - actual: [ 300, 350 ]

In the source, tile.size() is returning (x1, y1):

tile.size = function(_) {
  return arguments.length ? ... : [x1, y1];
};

Perhaps it should be changed to return (x1-x0, y1-y0)?

tile.size = function(_) {
  return arguments.length ? ... : [x1 - x0, y1 - y0];
};

Easier tile positioning?

It’s be nice to have a convenience method for computing tile positions. Currently I do something like:

x="${Math.round((x + tiles.translate[0]) * tiles.scale)}" y="${Math.round((y + tiles.translate[1]) * tiles.scale)}"

It’d be nice if there were a function on the tile generator that took a tile object and returned its [x, y] coordinates in screenspace as above.

https://observablehq.com/@d3/raster-tiles

set position in viewport

Hello,

Can you give me some help to set the initial position with tile rendering and d3-tile?
In my case I have to render an electric schema with tiles. The schema doesn't have a mercator projection, because it's a plane object.

I calculated the initial scale for the desired zoom factor we need but we miss the translation.

In the example I see:

// Apply a zoom transform equivalent to projection.{scale,translate,center}.
svg
.call(zoom)
.call(zoom.transform, d3.zoomIdentity
.translate(width / 2, height / 2)
.scale(1 << 12)
.translate(-center[0], -center[1]));

In the example center is a result of the mercator projection. so for my example I have some questions:

  1. What are the numbers in the second translate(...)? Which are the coordinates? Are they in the object unit? Or scaled?

  2. Applying this three operations in the sequence is something like:

    • moving the schema in the viewport
    • scale
    • moving the schema to the desidered position ?
  3. How can I translate and scale the schema to a particular coord? The example is the correct sequence of operations?

Thank you very much for the help

oufresh

Support maxNativeZoom

Most accessible tile sources provide tiles until a certain z-coordinate, e.g. z <= 19 for OpenStreetMap. While I could prevent zooming further in using zoom.scaleExtent(), I sometimes want to be able to zoom further in, while using tiles with less resolution.

Leaflet solves this problem with https://leafletjs.com/reference-1.5.0.html#gridlayer-maxnativezoom

I think it would be nice to solve this in d3-tile as well.

Rename tile.x and tile.y to tile.tx and tile.ty?

I feel like the distinction between tile[0] and tile.x is too small (or that the names are easily confused), especially since typically we substitute tile[0] as the %x variable in a URL template.

Maybe the names tile.tx and tile.ty would be better? Especially if they are premultiplied? Although I guess d3.zoomTransform uses {x, y, k}, so, I dunno.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.