Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/HarryStevens/swiftmap

A JavaScript library for making data-driven maps.
https://github.com/HarryStevens/swiftmap

Last synced: 18 days ago
JSON representation

A JavaScript library for making data-driven maps.

Awesome Lists containing this project

README

        

# Swiftmap
A JavaScript library for making data-driven maps. [See it in action](https://bl.ocks.org/harrystevens/5b705c13618e20706675135fd412b6d1).

Swiftmap is still in development mode (v0.x). This is not a stable release. The API is subject to breaking changes.

## Features

* Provides a simple API for making maps.

```js
var map = swiftmap.map()
.layerPolygons(UsaStatesTopoJSON, d => d.stateName)
.draw();
```

* Exposes DOM elements as D3 selections for styling.

```js
var colors = ["red", "orange", "yellow", "green", "blue", "purple"];
map.layers[0].polygons.style("fill", (d, i) => colors[i % colors.length]);
```

* Makes it easy to create resizable maps for responsive designs.

```js
window.onresize = () => map.resize();
```

* Uses simple abstractions for creating color schemes.

```js
var scheme = swiftmap.schemeSequential()
.data(UsaStatesByPopulation, d => d.stateName)
.from(d => d.population)
.to(["#ffffcc", "#a1dab4", "#41b6c4", "#2c7fb8", "#253494"]);

map.layers[0].polygons.style("fill", scheme);
```

## Installation

### Web browser
In vanilla, a `swiftmap` global is exported. You can use the CDN from unpkg.
```html

```
If you'd rather host it yourself, download `swiftmap.js` or `swiftmap.min.js` from the [`dist` directory](https://github.com/HarryStevens/swiftmap/tree/master/dist).
```html

```

### npm
```bash
npm install swiftmap --save
```
```js
var swiftmap = require("swiftmap");
```

## API Reference

- [Maps](#maps)
- [Layers](#layers)
- [Polygons](#layerPolygons)
- [Points](#layerPoints)
- [Schemes](#schemes)
- [Categorical](#schemeCategorical)
- [Continuous](#schemeContinuous)
- [Sequential](#schemeSequential)

### Maps

Before drawing and styling a map, you can tell Swiftmap where on the DOM to place the map. You may also specify a map projection and call methods for resizing the map when the browser window's dimensions change.

# swiftmap.map([parent]) [<>](https://github.com/HarryStevens/swiftmap/tree/master/src/map/map.js "Source")

Initializes a map.

parent

If parent is specified, the map will be placed in the DOM element referenced by the parent's selector. The parent must be specified as a string. If parent is not specified, `"body"` will be used as the parent. The map will inherit the dimensions of its parent.

# map.graticule([step]) [<>](https://github.com/HarryStevens/swiftmap/tree/master/src/map/graticule.js "Source")

Adds a graticule to the map. [See it in action](https://bl.ocks.org/HarryStevens/30daa8a31d0d444aceb55a58adedf7c8).

step

To set the frequency of the graticule's lines, a step may be specified as an array of two numbers, where the first number is the frequency in degrees of the lines of longitude, and the second number is the frequency in degrees of latitude. Defaults to `[10, 10]`.

# map.projection([projection]) [<>](https://github.com/HarryStevens/swiftmap/tree/master/src/map/projection.js "Source")

Sets or gets a map's projection.

projection

If projection is specified, sets the map's projection. The projection must be specified as a string, and can be one of three options:
- `"mercator"`, for the [Mercator projection](https://en.wikipedia.org/wiki/Mercator_projection)
- `"equirectangular"`, for the [equirectangular projection](https://en.wikipedia.org/wiki/Equirectangular_projection)
- `"albersUsa"`, for the Albers USA projection, which is a composite of three [Albers' equal-area conic projections](https://en.wikipedia.org/wiki/Albers_projection)

If projection is not specified, returns the projection associated with the map. For more information, see the [documentation in d3-geo](https://github.com/d3/d3-geo#projections).

# map.resize() [<>](https://github.com/HarryStevens/swiftmap/tree/master/src/map/resize.js "Source")

Resizes the map. This method is useful if your map must respond to window resizes.

# map.tiles([tilesource | tilefunction]) [<>](https://github.com/HarryStevens/swiftmap/tree/master/src/map/tiles.js "Source")

Adds raster tiles to the map's background and exposes the CSS class `tile`. Note that these raster tiles only work with a Mercator projection. If you use these raster tiles, please include a copyright notice with your map. [See it in action](https://bl.ocks.org/HarryStevens/e605a99d49878fac2e2117256608a3a4).

tilesource

You can specify a tilesource as a string to determine the style of raster tiles. Defaults to `"openStreetMap"`. Your options are:

- `"cartoDark"` Carto dark tiles. Copyright: Map tiles by [Carto](https://carto.com/location-data-services/basemaps/).
- `"cartoDarkLabels"` Carto dark tiles' labels. Copyright: Map tiles by [Carto](https://carto.com/location-data-services/basemaps/).
- `"cartoLight"` Carto light tiles. Copyright: Map tiles by [Carto](https://carto.com/location-data-services/basemaps/).
- `"cartoLightLabels"` Carto light tiles' labels. Copyright: Map tiles by [Carto](https://carto.com/location-data-services/basemaps/).
- `"cartoLightNoLabels"` Carto light tiles without labels. Copyright: Map tiles by [Carto](https://carto.com/location-data-services/basemaps/).
- `"mapboxNaturalEarth"` Mapbox Natural Earth II. Copyright: Map tiles by [MapBox](http://a.tiles.mapbox.com/v3/mapbox.natural-earth-2/page.html).
- `"openStreetMap"` Open Street Map tiles. Copyright: © [OpenStreetMap contributors](https://www.openstreetmap.org/copyright).
- `"stamenToner"` Stamen toner tiles. Copyright: Map tiles by [Stamen Design](http://stamen.com/), under [CC BY 3.0](http://creativecommons.org/licenses/by/3.0). Data by [OpenStreetMap](http://openstreetmap.org/), under [ODbL](http://www.openstreetmap.org/copyright).
- `"stamenTerrain"` Stamen terrain tiles. Copyright: Map tiles by [Stamen Design](http://stamen.com/), under [CC BY 3.0](http://creativecommons.org/licenses/by/3.0). Data by [OpenStreetMap](http://openstreetmap.org/), under [ODbL](http://www.openstreetmap.org/copyright).
- `"stamenTerrainLabels"` Stamen terrain tiles' labels. Copyright: Map tiles by [Stamen Design](http://stamen.com/), under [CC BY 3.0](http://creativecommons.org/licenses/by/3.0). Data by [OpenStreetMap](http://openstreetmap.org/), under [ODbL](http://www.openstreetmap.org/copyright).
- `"stamenTerrainNoLabels"` Stamen terrain tiles without labels. Copyright: Map tiles by [Stamen Design](http://stamen.com/), under [CC BY 3.0](http://creativecommons.org/licenses/by/3.0). Data by [OpenStreetMap](http://openstreetmap.org/), under [ODbL](http://www.openstreetmap.org/copyright).
- `"stamenWatercolor"` Stamen watercolor tiles. Copyright: Map tiles by [Stamen Design](http://stamen.com/), under [CC BY 3.0](http://creativecommons.org/licenses/by/3.0). Data by [OpenStreetMap](http://openstreetmap.org/), under [CC BY SA](http://creativecommons.org/licenses/by-sa/3.0).
- `"wikimedia"` Wikimedia tiles. Copyright: [Wikimedia](https://wikimediafoundation.org/wiki/Maps_Terms_of_Use) | © [OpenStreetMap](https://www.openstreetmap.org/copyright).

tilefunction

Instead of a tilesource, you can specify a tilefunction to generate a tiles URL. The tiles are generated by [d3-tile](https://github.com/d3/d3-tile) and have the properties `x`, `y`, `z`, `tx` and `ty`. You can [read more about these properties in the documentation](https://github.com/d3/d3-tile#_tile). For example, a tilefunction could be specified as:
```js
var tileGenerator = tile => "http://" + "abc"[tile.y % 3] + ".tile.openstreetmap.org/" + tile.z + "/" + tile.x + "/" + tile.y + ".png";

map.tiles(tileGenerator);
```

Map attributes

# map.height

# map.width

The map's dimensions.

# map.svg

The D3 selection of the SVG element containing the map.

# map.parent

A string of the map's parent element.

### Layers

Layers let you add geospatial data to a map, as well as decide how that data should be drawn to the DOM. The recommended indenting pattern is to indent two spaces to declare a new layer, calling either map.layerPolygons() or map.layerPoints(), and to indent four spaces when calling drawing functions on the preceding layer.

```js
var map = swiftmap.map("#map")
.layerPolygons(TopoJSON, d => d.state_name, "states")
.drawPolygons()
.drawBoundary()
.layerPolygons(TopoJSON, d => d.county_name, "counties")
.draw()
.layerPoints(TopoJSON, d => d.city_name, "cities")
.drawPoints()
.drawLabels(d => d.city_name);

map.layers[1].polygons.style("fill", scheme);
```

Layers can be styled with CSS selectors.

```css
#map .boundary {
stroke-width: 2px;
}
#map .boundary.boundary-states {
stroke-width: 3px;
}
#map .polygon {
fill: none;
}
#map .polygon.polygon-counties {
stroke-dasharray: 5, 5;
}
#map .point.point-cities {
fill: blue;
}
#map .label.label-cities {
font-size: 1.2em;
}
```

[See it in action](https://bl.ocks.org/HarryStevens/ef47557d3639243956e26261199ee91c).

# map.layerPolygons([data][, key][, layer]) [<>](https://github.com/HarryStevens/swiftmap/tree/master/src/map/layerPolygons.js "Source")

Sets or gets a polygons layer.

data

The data must be specified as a TopoJSON object. If no data is passed, returns the geospatial data associated with the layer.

key

Each datum will be assigned a key value based on the value returned by an optional key function. This key will be used to match each datum of geospatial data to a corresponding datum of tabular data when a scheme is passed to a style or attribute of the layer. If no key is specified, each datum will be assigned a key according to its index.

layer

If a layer is passed, the geospatial data will be associated with the name of the layer, which must be specified as a string. In the layer string, space characters will be converted to hyphens so that DOM elements produced by the layer's geospatial data can be referenced with CSS selectors.

If a layer is not passed, the geospatial data will be associated with the index of the layer, where the first layer is indexed to `0`. For instance, the name of the third layer added to the map will default to `2`, and can be styled with CSS using the following pattern:

```css
#map .boundary.boundary-2 {
stroke-width: 2px;
}
```

# polygons.draw([layer]) [<>](https://github.com/HarryStevens/swiftmap/tree/master/src/map/draw.js "Source")

Draws a polygons layer. This is a convenience method equivalent to map.fit().drawPolygons().drawBoundary().

layer

If layer is not specified, the most recently added layer will be drawn by default. If you wish to change the default behavior, you may specify a layer as a string or a number corresponding to a layer that has already been added to the map, and Swiftmap will draw or redraw the specified layer.

# polygons.drawBoundary([layer]) [<>](https://github.com/HarryStevens/swiftmap/tree/master/src/map/drawBoundary.js "Source")

Draws a polygons layer's outer boundary. The boundary is rendered as an SVG `path` element, can be accessed as a D3 selection via `map.layers.< layername >.boundary`, and can be styled with the CSS class `.boundary` or `.boundary-< layername >` or both.

layer

If layer is not specified, the boundary of the most recently added layer will be drawn by default. If you wish to change the default behavior, you may specify a layer as a string or a number corresponding to a layer that has already been added to the map, and Swiftmap will draw or redraw the boundary of the specified layer.

# map.layerPoints([data][, key][, layer]) [<>](https://github.com/HarryStevens/swiftmap/tree/master/src/map/layerPoints.js "Source")

Sets or gets a points layer. See [map.polygons()](#polygons) for descriptions of the arguments.

# polygons.drawLabels(key[,offset][, layer]) [<>](https://github.com/HarryStevens/swiftmap/tree/master/src/map/drawLabels.js "Source")

Labels each polygon at its [pole of inaccessibility](https://github.com/mapbox/polylabel) or, in the case of complex multipolygons, its [centroid](https://en.wikipedia.org/wiki/Centroid). Labels are rendered as SVG `text` elements, can be accessed as D3 selections via `map.layers.< layername >.labels`, and can be styled with the CSS class `.label` or `.label-< layername >` or both.

key

A key function tells Swiftmap how each datum should be labeled.

```js
var key = d => d.properties.name;

map.drawLabels(key);
```

offset

By default, labels are centered on the coordinates of the polygons' centroid. To offset the labels, you may specify the offset as `true`. If the polygons's centroid is on the left half of the map, the label will be placed to the left side of the point. If the polygons's centroid is on the right half of the map, the label will be placed to the right side of the point.

layer

If layer is not specified, the labels of the most recently added layer will be drawn by default. If you wish to change the default behavior, you may specify a layer as a string or a number corresponding to a layer that has already been added to the map, and Swiftmap will draw or redraw the labels of the specified layer.

# polygons.drawPoints([radius][, layer]) [<>](https://github.com/HarryStevens/swiftmap/tree/master/src/map/drawPoints.js "Source")

Draws points at the centroid of each polygon in a polygons layer. Points are rendered as SVG `circle` elements, can be accessed as D3 selections via `map.layers.< layername >.points`, and can be styled with the CSS class `.point` or `.point-< layername >` or both.

radius

If radius is specified, sets each point's radius in pixels. Defaults to `2`.

layer

If layer is not specified, the points of the most recently added layer will be drawn by default. If you wish to change the default behavior, you may specify a layer as a string or a number corresponding to a layer that has already been added to the map, and Swiftmap will draw or redraw the polygons of the specified layer.

# polygons.drawPolygons([layer]) [<>](https://github.com/HarryStevens/swiftmap/tree/master/src/map/drawPolygons.js "Source")

Draws a polygons layer's polygons. For example, if the layer's TopoJSON contains states, the polygons are the states. Polygons are rendered as SVG `path` elements, can be accessed as D3 selections via `map.layers.< layername >.polygons`, and can be styled with the CSS class `.polygon` or `.polygon-< layername >` or both.

layer

If layer is not specified, the polygons of the most recently added layer will be drawn by default. If you wish to change the default behavior, you may specify a layer as a string or a number corresponding to a layer that has already been added to the map, and Swiftmap will draw or redraw the polygons of the specified layer.

# polygons.fit([layer]) [<>](https://github.com/HarryStevens/swiftmap/tree/master/src/map/fit.js "Source")

Updates the projection so that a layer's outer boundary fits the map's parent element. Overrides any previous invocations of map.fit(), as the map can only have one projection.

layer

If layer is not specified, the most recently added layer will be fit to the boundary of the parent element. If you wish to change the default behavior, you may specify a layer as a string or a number corresponding to a layer that has already been added to the map, and Swiftmap will fit the specified layer's outer boundary to the parent element.

# map.layerPoints([data][, key][, layer]) [<>](https://github.com/HarryStevens/swiftmap/tree/master/src/map/layerPoints.js "Source")

Sets or gets a points layer. See [map.polygons()](#polygons) for descriptions of the arguments.

# points.drawLabels(key[,offset][, layer]) [<>](https://github.com/HarryStevens/swiftmap/tree/master/src/map/drawLabels.js "Source")

Labels the points. Labels are rendered as SVG `text` elements, can be accessed as D3 selections via `map.layers.< layername >.labels`, and can be styled with the CSS class `.label` or `.label-< layername >` or both.

key

A key function tells Swiftmap how each datum should be labeled.

```js
var key = d => d.properties.name;

map.drawLabels(key);
```

offset

By default, labels are centered on the coordinates of the point. To offset the labels, you may specify the offset as `true`. If the label's point is on the left half of the map, the label will be placed to the left side of the point. If the label's point is on the right half of the map, the label will be placed to the right side of the point.

layer

If layer is not specified, the labels of the most recently added layer will be drawn by default. If you wish to change the default behavior, you may specify a layer as a string or a number corresponding to a layer that has already been added to the map, and Swiftmap will draw or redraw the labels of the specified layer.

# points.drawPoints([radius][, layer]) [<>](https://github.com/HarryStevens/swiftmap/tree/master/src/map/drawPoints.js "Source")

Draws circles, located at each point's coordinates, to a layer. Points are rendered as SVG `circle` elements, can be accessed as D3 selections via `map.layers.< layername >.points`, and can be styled with the CSS class `.point` or `.point-< layername >` or both.

radius

If radius is specified, sets each point's radius in pixels. Defaults to `2`.

layer

If layer is not specified, the points of the most recently added layer will be drawn by default. If you wish to change the default behavior, you may specify a layer as a string or a number corresponding to a layer that has already been added to the map, and Swiftmap will draw or redraw the points of the specified layer.

# points.fit([layer]) [<>](https://github.com/HarryStevens/swiftmap/tree/master/src/map/fit.js "Source")

See [polygons.fit()](#fit-polygons).

### Schemes

Schemes provide an interface for mapping values of your data to visual attributes, such as a choropleth map's color palette or the radii of circles in a bubble map. Schemes can be added to a map like so:

```js
map.layers[0].style("fill", schemeSequential);
map.layers[1].attr("r", schemeContinuous);
map.layers[2].style("opacity", schemeCategorical);
```

[See it in action](https://bl.ocks.org/harrystevens/2fb3dce0b9f4930be9141bc6f418994f).

# swiftmap.schemeCategorical() [<>](https://github.com/HarryStevens/swiftmap/tree/master/src/scheme/schemeCategorical.js "Source")

Categorical schemes are used to assign styles or attributes of layer elements, such as polygons' fill color, to non-numerical categories of data, such as political parties in an election.

```js
var scheme = swiftmap.schemeCategorical()
.data(JSON, d => d.state)
.from(d => d.party)
.to({
"Republican": "tomato",
"Democratic": "steelblue"
})
.toOther("yellow");
```

[See it in action](https://bl.ocks.org/HarryStevens/bc32fe303275b00a2aeea96328a3b143).

# categorical.data([data][, key])

Adds data to a scheme, where each datum corresponds to each element of a layer.

data

The data must be specified as a JSON array. If no data is passed, returns the data associated with the scheme.

key

Each datum will be assigned a key value returned by an optional key function. This key will be used to match each datum of tabular data to a corresponding datum of geospatial data when the scheme is passed to a style or attribute of a layer. If no key is specified, each datum will be assigned a key according to its index.

# categorical.from(function)

Sets the values accessor to the specified function, allowing the scheme to interact with a layer's data.

function

When the scheme is passed to a style or attribute of a layer, the function will be called for each datum in the layer's data array, being passed the datum `d`, the index `i`, and the array `data` as three arguments. For example, if you want your scheme to be based on each polygon's party:

```js
var data = [
{party: "Democratic", state: "California"},
{party: "Republican", state: "Texas"},
...
];

scheme
.data(data, d => d.state)
.from(d => d.party);

map.layers[0].polygons.style("fill", scheme);
```

# categorical.to([object])

Specifies how the scheme should visually render the values returned by categorical.from().

object

If an object is specified, it must be specified as an object where each property is one of the scheme's categories – that is, a value returned by categorical.from() – and each value is the visual style or attribute associated with that category.

```js
scheme.to({
"Republican": "tomato",
"Democratic": "steelblue"
});
```

If object is not specified, returns the object associated with the scheme.

# categorical.toOther([value])

Sets or gets an alternative value in the scheme.

value

If a value is specified, assigns values to those DOM elements whose category is not present among the properties of the object passed to categorical.to(). If value is not specified, returns the scheme's alternative value, which defaults to `null`.

# swiftmap.schemeContinuous() [<>](https://github.com/HarryStevens/swiftmap/tree/master/src/scheme/schemeContinuous.js "Source")

Continuous schemes are used to map values of data to corresponding visual attributes along a continuum. You can use a continuous scheme to make a [bubble map](https://bl.ocks.org/harrystevens/2fb3dce0b9f4930be9141bc6f418994f) where the radius of each bubbble corresponds to the magnitude of each datum. You can also use a continuous scheme to create [choropleth maps with a gradient scale](https://bl.ocks.org/harrystevens/4608d25b2f424a2e011d7ab9cc804f4e).

```js
var scheme = swiftmap.schemeContinuous()
.data(JSON)
.from(d => d.value)
.to([2, 20]);
```

[See it in action](https://bl.ocks.org/HarryStevens/ab09e52c2d513ae7e6aa783cbd9dc1c3).

# continuous.data([data][, key])

See [categorical.data()](#data-categorical).

# continuous.from(function)

See [categorical.from()](#from-categorical).

# continuous.to([array])

Sets or gets the minimum and maximum values of a visual attribute associated with the scheme.

array

If a array is specified, sets the sequence of values of the the visual attribute associate with the scheme. The array can contain as many items as you like, and the scheme will map data values returned by continuous.from() to corresponding values in the array. If a array is not specified, returns the array associated with the scheme, which defaults to `[0, 1]`.

# continuous.toOther([value])

See [categorical.toOther()](#toOther-categorical).

# swiftmap.schemeSequential() [<>](https://github.com/HarryStevens/swiftmap/tree/master/src/scheme/schemeSequential.js "Source")

Sequential schemes are used to assign styles or attributes of layer elements, such as polygons' fill color, to discrete ranges in a series of values that progress from low to high.

```js
var scheme = swiftmap.schemeSequential()
.data(JSON)
.from(d => d.value)
.to(["#ffffcc", "#a1dab4", "#41b6c4", "#2c7fb8", "#253494"])
.breaks("q");
```

[See it in action](https://bl.ocks.org/HarryStevens/4db2b695df4b02042bfa0c1ee6eac299).

# sequential.breaks([breaktype | breaklist])

Computes class breaks based on data. If no argument is passed, returns the scheme's breaklist – an array of numbers representing the breaks associated with the scheme.

breaktype

If a breaktype is specified, the scheme will compute the class breaks based on the values returned by the function passed to [sequential.from()](#from-sequential). The breaktype must be specified as a string, either `"e"`, `"q"`, `"l"` or `"k"`.
- `"e"` specifies equidistant breaks, where each break spans an equal numeric range.
- `"l"` specifies logarithmic breaks, which are just like equidistant breaks but on a logarithmic scale.
- `"q"` specifies quantile breaks, where an equal number of data points are placed into each break.
- `"k"` specifies k-means breaks, which use a [k-means clustering](https://en.wikipedia.org/wiki/K-means_clustering) algorithm to group similar data points with each other.

The breaktype will default to `"q"` if sequential.breaks() is not called.

breaklist

If you'd rather use custom breaks, you can specify a breaklist as an array of numbers. The length of the breaklist should be one greater than the length of the array passed to [sequential.to()](#to-sequential), and its extent should span the range of values returned by the function passed to [sequential.from()](#from-sequential).

```js
var scheme = swiftmap.schemeSequential()
.from(d => d.value)
.to(["tomato", "lightblue", "steelblue", "darkblue"])
.breaks([-.5, 0, 20, 25, 55]);
```

[See it in action](https://bl.ocks.org/HarryStevens/9d052eec2ab33d0a84a4475030ede896).

# sequential.data([data][, key])

See [categorical.data()](#data-categorical).

# sequential.from(function)

See [categorical.from()](#from-categorical). For example, if you want your scheme to be based on each polygon's population density:

```js
var data = [
{population: "15324", area: "124", county: "Foo"},
{population: "23540", area: "365", county: "Bar"},
...
];

scheme
.data(data, d => d.county)
.from(d => +d.population / +d.area);

map.layers[0].polygons.style("fill", scheme);
```

# sequential.to([array])

Specifies the series of styles or attributes to which values should be assigned, such as a serious of color buckets in a choropleth map.

array

If an array is specified, the scheme will assign a series of values to each item in the array. If array is not specified, returns the array associated with the scheme.

The array will default to `[]` if this method is not called.

# sequential.toOther([value])

See [categorical.toOther()](#toOther-categorical).

## Contributing

```bash
git clone https://github.com/HarryStevens/swiftmap # clone this repository
cd swiftmap # navigate into the directory
npm install # install node modules
```

Swiftmap is compiled with [rollup](https://github.com/rollup/rollup). Each function can be found in the [`src` directory](https://github.com/HarryStevens/swiftmap/tree/master/lib).

```bash
npm run rollup # compile the library
npm run minify # minify the library
npm run build # compile and minify the library
```

Swiftmap also uses a custom version of D3.js, which can be found in [`lib/d3`](https://github.com/HarryStevens/swiftmap/tree/master/lib/d3). If you need to update the bundle, do `cd lib/d3`, where you can install additional dependencies and update the [`index.js`](https://github.com/HarryStevens/swiftmap/blob/master/lib/d3/index.js) file. You will also have to update the `globals` object and the `only` array in the `resolve()` function in [`rollup.config.js`](https://github.com/HarryStevens/swiftmap/blob/master/rollup.config.js).