@montmorill/geojson2svg
v2.1.0
Published
Converts geojson to svg/path string given svg viewport size and maps extent.
Readme
geojson2svg
Converts GeoJSON to an SVG string, given the SVG viewport size and map extent. geojson2svg can be used on the client side (in the browser, through a bundler) or server side (with Node.js).
- Installation
- Usage
- Basic Example
- Migration from 1.x to 2.x
- API
- Important points
- Development
- Changelog
- License
- Related useful articles
Installation
npm install @montmorill/geojson2svgUsage
geojson2svg is distributed as an ES module with TypeScript declarations included.
import { GeoJSON2SVG } from '@montmorill/geojson2svg'
const converter = new GeoJSON2SVG(options)
const svgStrings = converter.convert(geojson, options)For browser usage, bundle it with your favourite bundler (vite, esbuild, rollup, webpack, ...).
Basic Example
import { GeoJSON2SVG } from '@montmorill/geojson2svg'
const converter = new GeoJSON2SVG({
mapExtent: { left: -180, bottom: -90, right: 180, top: 90 },
viewportSize: { width: 200, height: 100 },
attributes: ['properties.class', 'properties.foo'],
r: 2,
})
const geojsonData = {
type: 'FeatureCollection',
features: [
{
type: 'Feature',
id: 'pt-1',
geometry: { type: 'Point', coordinates: [50, 50] },
properties: { foo: 'val-1', class: 'point-tree' },
},
{
type: 'Feature',
geometry: {
type: 'LineString',
coordinates: [[10, 10], [15, 20], [30, 10]],
},
properties: { id: 'ln-1', foo: 'val-2', class: 'line-road', bar: 'val' },
},
{
type: 'Feature',
id: 'pg-1',
geometry: {
type: 'LineString',
coordinates: [[30, 10], [40, 40], [20, 40], [10, 20], [30, 10]],
},
properties: { id: 'not-used', foo: 'val-3', class: 'polygon-pond' },
},
],
}
const svgStr = converter.convert(geojsonData)
console.log(svgStr)
// output
// [
// '<path d="M127.77777777777777,22.22222222222222 m-2,0 a2,2 0 1,1 4,0 a2,2 0 1,1 -4,0" class="point-tree" foo="val-1" id="pt-1"/>',
// '<path d="M105.55555555555556,44.44444444444444 108.33333333333333,38.888888888888886 116.66666666666666,44.44444444444444" class="line-road" foo="val-2" id="ln-1"/>',
// '<path d="M116.66666666666666,44.44444444444444 122.22222222222221,27.77777777777778 111.11111111111111,27.77777777777778 105.55555555555556,38.888888888888886 116.66666666666666,44.44444444444444" class="polygon-pond" foo="val-3" id="pg-1"/>',
// ]convert function returns an array of SVG elements' strings.
Migration from 1.x to 2.x
Default export as a function is removed. Now
geojson2svgexports classGeoJSON2SVG.With 1.x
const geojson2svg = require('geojson2svg') const converter = geojson2svg(options)Now with 2.x
import { GeoJSON2SVG } from '@montmorill/geojson2svg' const converter = new GeoJSON2SVG(options) const svgStrings = converter.convert(geojson, options)Default value of
mapExtentin 1.x was Web Mercator projection's full extent. In 2.x ifmapExtentis not provided themapExtentFromGeoJSONis considered to be true, that means the extent of the input data is considered asmapExtent.There is only one case (from 1.x to 2.x) for which your existing code would fail, the input GeoJSON data projection system is Web Mercator and you have not specified
mapExtent. So to work with 2.x just pass themapExtentas Web Mercator extent
API
Initializing the instance
const converter = new GeoJSON2SVG(options)Here are all options available for initializing the instance.
viewportSize is object containing width and height in pixels. Default viewportSize value is:
{width: 256, height: 256}mapExtent:
{"left": coordinate, "bottom": coordinate, "right": coordinate, "top": coordinate}. Coordinates should be in same projection as of GeoJSON data. NOTE: IfmapExtentis not defined, the parametermapExtentFromGeojsonis consideredtrue.mapExtentFromGeojson: boolean, if true
mapExtentis calculated from GeoJSON data that is passed in.convertfunction.fitTo: 'width' | 'height' Fit output SVG map to width or height. If nothing is provided, the program tries to fit the data within width or height so that full mapExtent is visible in viewport.
center: boolean, default is false. Center the converted content within the viewport instead of anchoring it to the top-left corner. With
fitTo, the content is centered along the axis that does not fill the viewport (cropping evenly on both sides if it overflows).coordinateConverter: 'function' to convert input GeoJSON coordinates while converting to SVG. This function should take coordinates of a point
[x,y]and returns transformed point[x, y].pointAsCircle: true | false, default is false. For point GeoJSON return circle element for option:
const options = { pointAsCircle: true }output SVG string would be:
'<circle cx="30" cy="40" r="1" />'r: radius of point SVG element
attributes: Attributes which are required to attach as SVG attributes from features can be passed here as list of path in feature or json object for static attributes, like shown here
dynamic
{"attributes": ["properties.foo", "properties.bar"]}output:
[<path foo="fooVal-1" bar="barVal-1" d="M0,0 20,10 106,40"/>]or static
{"attributes": {"class": "mapstyle"}}output:
'<path class="mapstyle" d="M0,0 20,10 106,40"/>'or dynamic and static both
const options = { attributes: [ { property: 'properties.foo', type: 'dynamic', key: 'id', }, { property: 'properties.baz', type: 'dynamic', }, { property: 'bar', value: 'barStatic', type: 'static', }, ], }output:
[ '<path d="M128,128 128.00638801979818,127.99361198020182" id="fooVal-1" baz="bazVal-1" bar="barStatic"/>']Note: If a feature does not have value at the mentioned path then the attribute key would not be attached to SVG string and no error would be thrown.
Pass
trueto attach all feature properties as SVG attributes:const options = { attributes: true }Values are stringified as-is (
nullbecomes"null"),undefinedvalues are skipped, and attribute values are XML escaped.explode: true | false, default is false. Should multigeojson be exploded to many SVG elements or not.
precision number, precision of output SVG coordinates. Default is false. A positive integer sets the number of decimal places. Any other value rounds coordinates to the nearest
10^(-precision):-2rounds to hundreds (105.55becomes100),-1to tens, and fractional values to fractional powers of 10 (e.g.-0.5rounds to steps of10^0.5 ≈ 3.16).output: 'svg'|'path' default is 'svg'
'svg' - SVG element string is returned like
'<path d="M0,0 20,10 106,40"/>''path' - path 'd' value is returned
'M0,0 20,10 106,40'a linestringcallback: function, accept function that will be called on every GeoJSON conversion with output string as one input variable e.g:
const options = { callback(svgString) { // do something with svgString }, }Callback function could be used to render SVG string.
Instance method
.convert(geojson, options)
The options 'attributes', 'r' and 'callback' can also be given in convert function's option. Example:
const svgStrings = convertor.convert(geojson, {
attributes: [],
r: 1,
callback: () => {},
})Important points
Coordinate projection: this library does not automatically project GeoJSON coordinates. If your input GeoJSON and
mapExtentcoordinates are in WGS84 (World Geodetic System) you should provide acoordinateConverterfunction to project the coordinate values to a system such as Web Mercator projection ('EPSG:3857') also known as Spherical Mercator. Web Mercator projection is used by many web mapping sites (OpenStreetMap, Google, Bing, and others). Geographic coordinates can be converted to Web Mercator Projection using packages like:Polygon holes:
PolygonandMultiPolygonSVG elements automatically getfill-rule="evenodd"so holes render correctly. Afill-rulepassed throughattributesoverrides it.Assigning id to SVG path, there are two ways to achieve this. The first is default, the converter reads it from GeoJSON data attributes
feature.properties.idorfeature.id. Another way is explicitly specify theidattributes in.convertmethod, pass id along with attributes likeconverter.convert(feature, {attributes: {id:'foo-1', class: 'bar'}}). Preference order is: first asidkey in attributes thenfeature.idand lastfeature.properties.id.Converting SVG string to HTML DOM element, the SVG strings returned by
convertmethod can be easily converted to HTML SVG elements. Intentionally I have kept the geojson2svg's output as string to make it more modular. Here is simple way to convert SVG strings to SVG elements with parse-svg or with any other parser. Read more about SVG string conversion to DOM Element here or here. The usage of 'parse-svg' is as follows:npm install parse-svgSimple way to convert svgStrings to SVG elements
import parseSVG from 'parse-svg' const svgElements = svgStrings.map(parseSVG)
Development
npm install
npm run build # compile TypeScript sources to dist/ (tsc)
npm test # build then run the mocha test suite
npm run lint # eslint
npm run watch # tsc -wThe test/ suite compares the built dist/ output against the expected path/svg strings for every geometry type and option.
Changelog
Check here
License
This project is licensed under the terms of the MIT license.
