Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

geojson2svg

Package Overview
Dependencies
Maintainers
1
Versions
42
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

geojson2svg - npm Package Compare versions

Comparing version 1.3.6 to 2.0.0

examples/nodejs-example-basic.js

10

CHANGELOG.md

@@ -7,2 +7,12 @@ ### Changelog

### [v2.0.0](https://github.com/gagan-bansal/geojson2svg/compare/v1.3.6...v2.0.0)
> 28 July 2023
- feat: 1) mapExtent can be calculated from GeoJSON data 2) coordinate converter option added [`6fb06d0`](https://github.com/gagan-bansal/geojson2svg/commit/6fb06d07936ceccd6f99a784912588f313a34e64)
- fix: dev dependecy update [`983eef0`](https://github.com/gagan-bansal/geojson2svg/commit/983eef06158484ded52bfa99bffc1b0f86d596fc)
- improvement: export as a class GeoJSON2SVG [`066a072`](https://github.com/gagan-bansal/geojson2svg/commit/066a072fb523a131c20535d5a40ecd588169c538)
- feat: Type Declaration file added [`53b35cf`](https://github.com/gagan-bansal/geojson2svg/commit/53b35cf59695f0197dbff6de3cd2a692385b68ba)
- docs: readme update [`838fedd`](https://github.com/gagan-bansal/geojson2svg/commit/838fedd765bb3779a84d581ad6efe6437c8def07)
#### [v1.3.6](https://github.com/gagan-bansal/geojson2svg/compare/v1.3.5...v1.3.6)

@@ -9,0 +19,0 @@

311

dist/geojson2svg.js

@@ -1,2 +0,172 @@

(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.geojson2svg = f()}})(function(){var define,module,exports;return (function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){
(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.GeoJSON2SVG = f()}})(function(){var define,module,exports;return (function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){
const {GeoJSON2SVG} = require('./src/index.js');
module.exports = GeoJSON2SVG;
},{"./src/index.js":6}],2:[function(require,module,exports){
'use strict';
var hasOwn = Object.prototype.hasOwnProperty;
var toStr = Object.prototype.toString;
var defineProperty = Object.defineProperty;
var gOPD = Object.getOwnPropertyDescriptor;
var isArray = function isArray(arr) {
if (typeof Array.isArray === 'function') {
return Array.isArray(arr);
}
return toStr.call(arr) === '[object Array]';
};
var isPlainObject = function isPlainObject(obj) {
if (!obj || toStr.call(obj) !== '[object Object]') {
return false;
}
var hasOwnConstructor = hasOwn.call(obj, 'constructor');
var hasIsPrototypeOf = obj.constructor && obj.constructor.prototype && hasOwn.call(obj.constructor.prototype, 'isPrototypeOf');
// Not own constructor property must be Object
if (obj.constructor && !hasOwnConstructor && !hasIsPrototypeOf) {
return false;
}
// Own properties are enumerated firstly, so to speed up,
// if last one is own, then all properties are own.
var key;
for (key in obj) { /**/ }
return typeof key === 'undefined' || hasOwn.call(obj, key);
};
// If name is '__proto__', and Object.defineProperty is available, define __proto__ as an own property on target
var setProperty = function setProperty(target, options) {
if (defineProperty && options.name === '__proto__') {
defineProperty(target, options.name, {
enumerable: true,
configurable: true,
value: options.newValue,
writable: true
});
} else {
target[options.name] = options.newValue;
}
};
// Return undefined instead of __proto__ if '__proto__' is not an own property
var getProperty = function getProperty(obj, name) {
if (name === '__proto__') {
if (!hasOwn.call(obj, name)) {
return void 0;
} else if (gOPD) {
// In early versions of node, obj['__proto__'] is buggy when obj has
// __proto__ as an own property. Object.getOwnPropertyDescriptor() works.
return gOPD(obj, name).value;
}
}
return obj[name];
};
module.exports = function extend() {
var options, name, src, copy, copyIsArray, clone;
var target = arguments[0];
var i = 1;
var length = arguments.length;
var deep = false;
// Handle a deep copy situation
if (typeof target === 'boolean') {
deep = target;
target = arguments[1] || {};
// skip the boolean and the target
i = 2;
}
if (target == null || (typeof target !== 'object' && typeof target !== 'function')) {
target = {};
}
for (; i < length; ++i) {
options = arguments[i];
// Only deal with non-null/undefined values
if (options != null) {
// Extend the base object
for (name in options) {
src = getProperty(target, name);
copy = getProperty(options, name);
// Prevent never-ending loop
if (target !== copy) {
// Recurse if we're merging plain objects or arrays
if (deep && copy && (isPlainObject(copy) || (copyIsArray = isArray(copy)))) {
if (copyIsArray) {
copyIsArray = false;
clone = src && isArray(src) ? src : [];
} else {
clone = src && isPlainObject(src) ? src : {};
}
// Never move original objects, clone them
setProperty(target, { name: name, newValue: extend(deep, clone, copy) });
// Don't bring in undefined values
} else if (typeof copy !== 'undefined') {
setProperty(target, { name: name, newValue: copy });
}
}
}
}
}
// Return the modified object
return target;
};
},{}],3:[function(require,module,exports){
module.exports = function(gj) {
var coords, bbox;
if (!gj.hasOwnProperty('type')) return;
coords = getCoordinatesDump(gj);
bbox = [ Number.POSITIVE_INFINITY,Number.POSITIVE_INFINITY,
Number.NEGATIVE_INFINITY, Number.NEGATIVE_INFINITY,];
return coords.reduce(function(prev,coord) {
return [
Math.min(coord[0], prev[0]),
Math.min(coord[1], prev[1]),
Math.max(coord[0], prev[2]),
Math.max(coord[1], prev[3])
];
}, bbox);
};
function getCoordinatesDump(gj) {
var coords;
if (gj.type == 'Point') {
coords = [gj.coordinates];
} else if (gj.type == 'LineString' || gj.type == 'MultiPoint') {
coords = gj.coordinates;
} else if (gj.type == 'Polygon' || gj.type == 'MultiLineString') {
coords = gj.coordinates.reduce(function(dump,part) {
return dump.concat(part);
}, []);
} else if (gj.type == 'MultiPolygon') {
coords = gj.coordinates.reduce(function(dump,poly) {
return dump.concat(poly.reduce(function(points,part) {
return points.concat(part);
},[]));
},[]);
} else if (gj.type == 'Feature') {
coords = getCoordinatesDump(gj.geometry);
} else if (gj.type == 'GeometryCollection') {
coords = gj.geometries.reduce(function(dump,g) {
return dump.concat(getCoordinatesDump(g));
},[]);
} else if (gj.type == 'FeatureCollection') {
coords = gj.features.reduce(function(dump,f) {
return dump.concat(getCoordinatesDump(f));
},[]);
}
return coords;
}
},{}],4:[function(require,module,exports){
//index.js

@@ -52,8 +222,12 @@ (function() {

},{}],2:[function(require,module,exports){
},{}],5:[function(require,module,exports){
//converter.js
var multi = require('multigeojson');
function getCoordString(coords,res,origin, precision) {
function getCoordString(coords,res,origin, precision, opt) {
//origin - svg image origin
var convertedCoords = coords.map(function(coord) {
if (opt.coordinateConverter) {
coord = opt.coordinateConverter(coord);
}
return [(coord[0] - origin.x)/res, (origin.y - coord[1])/res];

@@ -84,3 +258,3 @@ });

? opt.pointAsCircle : false;
var coords = getCoordString([geom.coordinates],res,origin,opt.precision);
var coords = getCoordString([geom.coordinates],res,origin,opt.precision, opt);
if (pointAsCircle) {

@@ -106,3 +280,3 @@ return [coords];

function lineString(geom,res,origin,opt) {
var coords = getCoordString(geom.coordinates,res,origin,opt.precision);
var coords = getCoordString(geom.coordinates,res,origin,opt.precision, opt);
var path = 'M'+ coords;

@@ -121,3 +295,3 @@ return [path];

var mainStr,holes,holeStr;
mainStr = getCoordString(geom.coordinates[0],res,origin,opt.precision);
mainStr = getCoordString(geom.coordinates[0],res,origin,opt.precision, opt);
if (geom.coordinates.length > 1) {

@@ -129,3 +303,3 @@ holes = geom.coordinates.slice(1,geom.coordinates.length);

for(var i=0;i<holes.length; i++) {
path += ' M' + getCoordString(holes[i],res,origin,opt.precision);
path += ' M' + getCoordString(holes[i],res,origin,opt.precision, opt);
}

@@ -153,36 +327,51 @@ }

},{"multigeojson":1}],3:[function(require,module,exports){
// extend.js
// extend b to a with shallow copy
module.exports = function(a, b) {
var c = {}
Object.keys(a).forEach(function(key) {
c[key] = a[key]
})
Object.keys(b).forEach(function(key) {
c[key] = b[key]
})
return c
}
},{}],4:[function(require,module,exports){
var extend = require('./extend.js');
},{"multigeojson":4}],6:[function(require,module,exports){
var bbox = require('geojson-bbox');
var extend = require('extend');
var converter = require('./converter.js');
//g2svg as geojson2svg (shorthand)
var g2svg = function(options) {
this.options = options || {};
this.viewportSize = this.options.viewportSize ||
var GeoJSON2SVG = function(options = {}) {
if (!options.mapExtent) {
// throw new
// Error('One of the parameter is must: mapExtent or mapExtentFromGeojson');
this.mapExtentFromGeojson = true;
} else {
this.mapExtentFromGeojson = options.mapExtentFromGeojson;
}
if (options.fitTo && !/^(width|height)$/i.test(options.fitTo)) {
throw new Error('"fitTo" option should be "width" or "height" ');
}
this.options = options;
this.viewportSize = options.viewportSize ||
{width: 256, height: 256};
this.mapExtent = this.options.mapExtent ||
{
left: -20037508.342789244,
right: 20037508.342789244,
bottom: -20037508.342789244,
top: 20037508.342789244
if (options.coordinateCoverter
&& typeof options.coordinateConverter != 'function')
{
throw new Error('"coordinateConverter" option should be function');
}
this.coordinateConverter = options.coordinateConverter;
if (options.mapExtent && this.coordinateConverter) {
var rightTop = this.coordinateConverter(
[options.mapExtent.right, options.mapExtent.top]);
var leftBottom = this.coordinateConverter(
[options.mapExtent.left, options.mapExtent.bottom]);
this.mapExtent = {
left: leftBottom[0], bottom: leftBottom[1],
right: rightTop[0], top: rightTop[1]
};
this.res = this.calResolution(this.mapExtent,this.viewportSize,
this.options.fitTo);
} else {
// yes, it may be undefined in case of mapExtentFromGeojson is true
this.mapExtent = options.mapExtent;
}
if (this.mapExtent) {
this.res = this.calResolution(this.mapExtent,this.viewportSize,
this.options.fitTo);
}
};
g2svg.prototype.calResolution = function(extent,size,fitTo) {
function convertExtent (extent, converter) {
var leftBottom = converter([extent[0], extent[1]]);
var rightTop = converter([extent[2], extent[3]]);
return [...leftBottom, ...rightTop];
}
GeoJSON2SVG.prototype.calResolution = function(extent,size,fitTo) {
var xres = (extent.right - extent.left)/size.width;

@@ -202,4 +391,22 @@ var yres = (extent.top - extent.bottom)/size.height;

};
g2svg.prototype.convert = function(geojson,options) {
var opt = extend(this.options, options || {});
GeoJSON2SVG.prototype.convert = function(geojson,options) {
var resetExtent = false;
if (!this.res && this.mapExtentFromGeojson) {
var resetExtent = true;
var extent = bbox(geojson); // output extent is an array
if (this.coordinateConverter) {
// var rightTop = this.coordinateConverter(extent[2] , extent[3]);
// var leftBottom = this.coordinateConverter(extent[0], extent[1]);
// extent = [leftBottom[0], leftBottom[1],
// rightTop[0], rightTop[1]];
extent = convertExtent(extent, this.coordinateConverter);
}
this.mapExtent = {
left: extent[0], bottom: extent[1],
right: extent[2], top: extent[3]
};
this.res = this.calResolution(
this.mapExtent, this.viewportSize, this.options.fitTo);
}
var opt = extend(true, {}, this.options, options || {});
var multiGeometries = ['MultiPoint','MultiLineString','MultiPolygon'];

@@ -223,10 +430,14 @@ var geometries = ['Point', 'LineString', 'Polygon'];

} else {
return;
throw new Error('Geojson type not supported.');
}
if (resetExtent) {
this.res = null;
this.mapExtent = null;
}
if(opt.callback) opt.callback.call(this,svgElements);
return svgElements;
};
g2svg.prototype.convertFeature = function(feature,options) {
GeoJSON2SVG.prototype.convertFeature = function(feature,options) {
if(!feature && !feature.geometry) return;
var opt = extend(this.options, options || {});
var opt = extend(true, {}, this.options, options || {});
if (opt.attributes && opt.attributes instanceof Array) {

@@ -270,5 +481,5 @@ var arr = opt.attributes

};
g2svg.prototype.convertGeometry = function(geom,options) {
GeoJSON2SVG.prototype.convertGeometry = function(geom,options) {
if(converter[geom.type]) {
var opt = extend(this.options, options || {});
var opt = extend(true, {}, this.options, options || {});
var output = opt.output || 'svg';

@@ -293,3 +504,3 @@ var paths = converter[geom.type].call(this,geom,

} else {
return;
throw new Error('Geojson type not supported.');
}

@@ -343,14 +554,6 @@ };

}
module.exports = g2svg;
module.exports = {GeoJSON2SVG};
},{"./converter.js":2,"./extend.js":3}],5:[function(require,module,exports){
var g2svg = require('./instance.js');
var geojson2svg = function(options) {
return new g2svg(options);
};
module.exports = geojson2svg;
},{"./instance.js":4}]},{},[5])(5)
},{"./converter.js":5,"extend":2,"geojson-bbox":3}]},{},[1])(1)
});
//# sourceMappingURL=geojson2svg.js.map

2

dist/geojson2svg.min.js

@@ -1,1 +0,1 @@

!function(f){"object"==typeof exports&&"undefined"!=typeof module?module.exports=f():"function"==typeof define&&define.amd?define([],f):("undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this).geojson2svg=f()}(function(){return function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var p="function"==typeof require&&require;if(!f&&p)return p(i,!0);if(u)return u(i,!0);throw(p=new Error("Cannot find module '"+i+"'")).code="MODULE_NOT_FOUND",p}p=n[i]={exports:{}},e[i][0].call(p.exports,function(r){return o(e[i][1][r]||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}({1:[function(require,module,exports){var singles,multies,multigeojson;singles=["Point","LineString","Polygon"],multies=["MultiPoint","MultiLineString","MultiPolygon"],multigeojson={explode:function(g){return-1<multies.indexOf(g.type)&&g.coordinates.map(function(part){var single={};return single.type=g.type.replace("Multi",""),single.coordinates=part,g.crs&&(single.crs=g.crs),single})},implode:function(gs){var sameType=gs.every(function(g){return-1<singles.indexOf(g.type)}),crs=gs[0].crs||0,sameCrs=gs.every(function(g){return(g.crs||0)==crs});if(sameType&&sameCrs){var multi={};return multi.type="Multi"+gs[0].type,multi.coordinates=[],0!=crs&&(multi.crs=crs),gs.forEach(function(g){multi.coordinates.push(g.coordinates)}),multi}return!1}},void 0!==module&&module.exports?module.exports=multigeojson:window&&(window.multigeojson=multigeojson)},{}],2:[function(require,module,exports){var multi=require("multigeojson");function getCoordString(coords,res,origin,precision){return coords.map(function(coord){return[(coord[0]-origin.x)/res,(origin.y-coord[1])/res]}).map(function(coord){return precision?coord[0].toFixed(precision)+","+coord[1].toFixed(precision):coord[0]+","+coord[1]}).join(" ")}function point(geom,res,origin,coords){var r=coords&&coords.r?coords.r:1,pointAsCircle=!(!coords||!coords.hasOwnProperty("pointAsCircle"))&&coords.pointAsCircle,coords=getCoordString([geom.coordinates],res,origin,coords.precision);return pointAsCircle?[coords]:["M"+coords+" m"+-r+",0 a"+r+","+r+" 0 1,1 "+2*r+",0 a"+r+","+r+" 0 1,1 "+-2*r+",0"]}function lineString(geom,res,origin,opt){return["M"+getCoordString(geom.coordinates,res,origin,opt.precision)]}function polygon(geom,res,origin,opt){var holes,path="M"+getCoordString(geom.coordinates[0],res,origin,opt.precision);if(holes=1<geom.coordinates.length?geom.coordinates.slice(1,geom.coordinates.length):holes)for(var i=0;i<holes.length;i++)path+=" M"+getCoordString(holes[i],res,origin,opt.precision);return[path+="Z"]}module.exports={Point:point,MultiPoint:function(paths,res,origin,opt){var explode=!(!opt||!opt.hasOwnProperty("explode"))&&opt.explode,paths=multi.explode(paths).map(function(single){return point(single,res,origin,opt)[0]});return explode?paths:[paths.join(" ")]},LineString:lineString,MultiLineString:function(paths,res,origin,opt){var explode=!(!opt||!opt.hasOwnProperty("explode"))&&opt.explode,paths=multi.explode(paths).map(function(single){return lineString(single,res,origin,opt)[0]});return explode?paths:[paths.join(" ")]},Polygon:polygon,MultiPolygon:function(paths,res,origin,opt){var explode=!!opt.hasOwnProperty("explode")&&opt.explode,paths=multi.explode(paths).map(function(single){return polygon(single,res,origin,opt)[0]});return explode?paths:[paths.join(" ").replace(/Z/g,"")+"Z"]}}},{multigeojson:1}],3:[function(require,module,exports){module.exports=function(a,b){var c={};return Object.keys(a).forEach(function(key){c[key]=a[key]}),Object.keys(b).forEach(function(key){c[key]=b[key]}),c}},{}],4:[function(g2svg,module,exports){var extend=g2svg("./extend.js"),converter=g2svg("./converter.js"),g2svg=function(options){this.options=options||{},this.viewportSize=this.options.viewportSize||{width:256,height:256},this.mapExtent=this.options.mapExtent||{left:-20037508.342789244,right:20037508.342789244,bottom:-20037508.342789244,top:20037508.342789244},this.res=this.calResolution(this.mapExtent,this.viewportSize,this.options.fitTo)};function valueAt(obj,path){return path.split(".").reduce(function(prev,cur,i,arr){if(prev.hasOwnProperty(cur))return prev[cur];throw new Error(arr.slice(0,i+1).join(".")+" is not a valid property path")},obj)}g2svg.prototype.calResolution=function(extent,yres,fitTo){var xres=(extent.right-extent.left)/yres.width,yres=(extent.top-extent.bottom)/yres.height;if(fitTo){if("width"===fitTo.toLowerCase())return xres;if("height"===fitTo.toLowerCase())return yres;throw new Error('"fitTo" option should be "width" or "height" ')}return Math.max(xres,yres)},g2svg.prototype.convert=function(geojson,options){var opt=extend(this.options,options||{}),svgElements=[];if("FeatureCollection"==geojson.type)for(var i=0;i<geojson.features.length;i++)svgElements=svgElements.concat(this.convertFeature(geojson.features[i],opt));else if("Feature"==geojson.type)svgElements=this.convertFeature(geojson,opt);else if("GeometryCollection"==geojson.type)for(i=0;i<geojson.geometries.length;i++)svgElements=svgElements.concat(this.convertGeometry(geojson.geometries[i],opt));else{if(!converter[geojson.type])return;svgElements=this.convertGeometry(geojson,opt)}return opt.callback&&opt.callback.call(this,svgElements),svgElements},g2svg.prototype.convertFeature=function(feature,opt){if(feature||feature.geometry){opt=extend(this.options,opt||{});opt.attributes&&opt.attributes instanceof Array?(id=opt.attributes,opt.attributes=id.reduce(function(sum,property){if("string"==typeof property){var key=property.split(".").pop();try{val=valueAt(feature,property)}catch(e){val=!1}val&&(sum[key]=val)}else if("object"==typeof property&&property.type&&property.property)if("dynamic"===property.type){var val,key=property.key||property.property.split(".").pop();try{val=valueAt(feature,property.property)}catch(e){val=!1}val&&(sum[key]=val)}else"static"===property.type&&property.value&&(sum[property.property]=property.value);return sum},{})):opt.attributes=opt.attributes||{};var id=opt.attributes.id||feature.id||(feature.properties&&feature.properties.id?feature.properties.id:null);return id&&(opt.attributes.id=id),this.convertGeometry(feature.geometry,opt)}},g2svg.prototype.convertGeometry=function(geom,paths){if(converter[geom.type]){var opt=extend(this.options,paths||{}),output=opt.output||"svg",paths=converter[geom.type].call(this,geom,this.res,{x:this.mapExtent.left,y:this.mapExtent.top},opt);return"svg"==output.toLowerCase()?paths.map(function(path){return function(path,type,attributes,opt){var key,svg={},pointAsCircle=!(!opt||!opt.hasOwnProperty("pointAsCircle"))&&opt.pointAsCircle;"Point"!=type&&"MultiPoint"!=type||!pointAsCircle?(svg={d:path},"Polygon"!=type&&"MultiPolygon"!=type||svg["fill-rule"]):(svg.cx=path.split(",")[0],svg.cy=path.split(",")[1],svg.r=opt&&opt.r?opt.r:"1");for(key in attributes)svg[key]=attributes[key];return svg}(path,geom.type,opt.attributes,opt)}).map(function(json){return function(json,type,pointAsCircle){var key,pointAsCircle=!(!pointAsCircle||!pointAsCircle.hasOwnProperty("pointAsCircle"))&&pointAsCircle.pointAsCircle,ele="<path";"Point"!=type&&"MultiPoint"!=type||!pointAsCircle||(ele="<circle");for(key in json)ele+=" "+key+'="'+json[key]+'"';return ele+="/>"}(json,geom.type,opt)}):paths}},module.exports=g2svg},{"./converter.js":2,"./extend.js":3}],5:[function(require,module,exports){var g2svg=require("./instance.js");module.exports=function(options){return new g2svg(options)}},{"./instance.js":4}]},{},[5])(5)});
!function(f){"object"==typeof exports&&"undefined"!=typeof module?module.exports=f():"function"==typeof define&&define.amd?define([],f):("undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this).GeoJSON2SVG=f()}(function(){return function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);throw(f=new Error("Cannot find module '"+i+"'")).code="MODULE_NOT_FOUND",f}c=n[i]={exports:{}},e[i][0].call(c.exports,function(r){return o(e[i][1][r]||r)},c,c.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}({1:[function(require,module,exports){require=require("./src/index.js").GeoJSON2SVG;module.exports=require},{"./src/index.js":6}],2:[function(require,module,exports){"use strict";function isArray(arr){return"function"==typeof Array.isArray?Array.isArray(arr):"[object Array]"===toStr.call(arr)}function isPlainObject(obj){if(obj&&"[object Object]"===toStr.call(obj)){var key,hasOwnConstructor=hasOwn.call(obj,"constructor"),hasIsPrototypeOf=obj.constructor&&obj.constructor.prototype&&hasOwn.call(obj.constructor.prototype,"isPrototypeOf");if(!obj.constructor||hasOwnConstructor||hasIsPrototypeOf){for(key in obj);return void 0===key||hasOwn.call(obj,key)}}}function setProperty(target,options){defineProperty&&"__proto__"===options.name?defineProperty(target,options.name,{enumerable:!0,configurable:!0,value:options.newValue,writable:!0}):target[options.name]=options.newValue}function getProperty(obj,name){if("__proto__"===name){if(!hasOwn.call(obj,name))return;if(gOPD)return gOPD(obj,name).value}return obj[name]}var hasOwn=Object.prototype.hasOwnProperty,toStr=Object.prototype.toString,defineProperty=Object.defineProperty,gOPD=Object.getOwnPropertyDescriptor;module.exports=function extend(){var options,name,copy,copyIsArray,src,target=arguments[0],i=1,length=arguments.length,deep=!1;for("boolean"==typeof target&&(deep=target,target=arguments[1]||{},i=2),(null==target||"object"!=typeof target&&"function"!=typeof target)&&(target={});i<length;++i)if(null!=(options=arguments[i]))for(name in options)src=getProperty(target,name),target!==(copy=getProperty(options,name))&&(deep&&copy&&(isPlainObject(copy)||(copyIsArray=isArray(copy)))?(src=copyIsArray?(copyIsArray=!1,src&&isArray(src)?src:[]):src&&isPlainObject(src)?src:{},setProperty(target,{name:name,newValue:extend(deep,src,copy)})):void 0!==copy&&setProperty(target,{name:name,newValue:copy}));return target}},{}],3:[function(require,module,exports){module.exports=function(gj){var bbox;if(gj.hasOwnProperty("type"))return gj=function getCoordinatesDump(gj){var coords;"Point"==gj.type?coords=[gj.coordinates]:"LineString"==gj.type||"MultiPoint"==gj.type?coords=gj.coordinates:"Polygon"==gj.type||"MultiLineString"==gj.type?coords=gj.coordinates.reduce(function(dump,part){return dump.concat(part)},[]):"MultiPolygon"==gj.type?coords=gj.coordinates.reduce(function(dump,poly){return dump.concat(poly.reduce(function(points,part){return points.concat(part)},[]))},[]):"Feature"==gj.type?coords=getCoordinatesDump(gj.geometry):"GeometryCollection"==gj.type?coords=gj.geometries.reduce(function(dump,g){return dump.concat(getCoordinatesDump(g))},[]):"FeatureCollection"==gj.type&&(coords=gj.features.reduce(function(dump,f){return dump.concat(getCoordinatesDump(f))},[]));return coords}(gj),bbox=[Number.POSITIVE_INFINITY,Number.POSITIVE_INFINITY,Number.NEGATIVE_INFINITY,Number.NEGATIVE_INFINITY],gj.reduce(function(prev,coord){return[Math.min(coord[0],prev[0]),Math.min(coord[1],prev[1]),Math.max(coord[0],prev[2]),Math.max(coord[1],prev[3])]},bbox)}},{}],4:[function(require,module,exports){var singles,multies,multigeojson;singles=["Point","LineString","Polygon"],multies=["MultiPoint","MultiLineString","MultiPolygon"],multigeojson={explode:function(g){return-1<multies.indexOf(g.type)&&g.coordinates.map(function(part){var single={};return single.type=g.type.replace("Multi",""),single.coordinates=part,g.crs&&(single.crs=g.crs),single})},implode:function(gs){var multi,sameType=gs.every(function(g){return-1<singles.indexOf(g.type)}),crs=gs[0].crs||0,sameCrs=gs.every(function(g){return(g.crs||0)==crs});return!(!sameType||!sameCrs)&&((multi={}).type="Multi"+gs[0].type,multi.coordinates=[],0!=crs&&(multi.crs=crs),gs.forEach(function(g){multi.coordinates.push(g.coordinates)}),multi)}},void 0!==module&&module.exports?module.exports=multigeojson:window&&(window.multigeojson=multigeojson)},{}],5:[function(require,module,exports){var multi=require("multigeojson");function getCoordString(coords,res,origin,precision,opt){return coords.map(function(coord){return[((coord=opt.coordinateConverter?opt.coordinateConverter(coord):coord)[0]-origin.x)/res,(origin.y-coord[1])/res]}).map(function(coord){return precision?coord[0].toFixed(precision)+","+coord[1].toFixed(precision):coord[0]+","+coord[1]}).join(" ")}function point(geom,res,origin,opt){var r=opt&&opt.r?opt.r:1,pointAsCircle=!(!opt||!opt.hasOwnProperty("pointAsCircle"))&&opt.pointAsCircle,geom=getCoordString([geom.coordinates],res,origin,opt.precision,opt);return pointAsCircle?[geom]:["M"+geom+" m"+-r+",0 a"+r+","+r+" 0 1,1 "+2*r+",0 a"+r+","+r+" 0 1,1 "+-2*r+",0"]}function lineString(geom,res,origin,opt){return["M"+getCoordString(geom.coordinates,res,origin,opt.precision,opt)]}function polygon(geom,res,origin,opt){var holes,path="M"+getCoordString(geom.coordinates[0],res,origin,opt.precision,opt);if(holes=1<geom.coordinates.length?geom.coordinates.slice(1,geom.coordinates.length):holes)for(var i=0;i<holes.length;i++)path+=" M"+getCoordString(holes[i],res,origin,opt.precision,opt);return[path+="Z"]}module.exports={Point:point,MultiPoint:function(geom,res,origin,opt){var explode=!(!opt||!opt.hasOwnProperty("explode"))&&opt.explode,geom=multi.explode(geom).map(function(single){return point(single,res,origin,opt)[0]});return explode?geom:[geom.join(" ")]},LineString:lineString,MultiLineString:function(geom,res,origin,opt){var explode=!(!opt||!opt.hasOwnProperty("explode"))&&opt.explode,geom=multi.explode(geom).map(function(single){return lineString(single,res,origin,opt)[0]});return explode?geom:[geom.join(" ")]},Polygon:polygon,MultiPolygon:function(geom,res,origin,opt){var explode=!!opt.hasOwnProperty("explode")&&opt.explode,geom=multi.explode(geom).map(function(single){return polygon(single,res,origin,opt)[0]});return explode?geom:[geom.join(" ").replace(/Z/g,"")+"Z"]}}},{multigeojson:4}],6:[function(require,module,exports){function GeoJSON2SVG(options={}){if(options.mapExtent?this.mapExtentFromGeojson=options.mapExtentFromGeojson:this.mapExtentFromGeojson=!0,options.fitTo&&!/^(width|height)$/i.test(options.fitTo))throw new Error('"fitTo" option should be "width" or "height" ');if(this.options=options,this.viewportSize=options.viewportSize||{width:256,height:256},options.coordinateCoverter&&"function"!=typeof options.coordinateConverter)throw new Error('"coordinateConverter" option should be function');var rightTop,leftBottom;this.coordinateConverter=options.coordinateConverter,options.mapExtent&&this.coordinateConverter?(rightTop=this.coordinateConverter([options.mapExtent.right,options.mapExtent.top]),leftBottom=this.coordinateConverter([options.mapExtent.left,options.mapExtent.bottom]),this.mapExtent={left:leftBottom[0],bottom:leftBottom[1],right:rightTop[0],top:rightTop[1]}):this.mapExtent=options.mapExtent,this.mapExtent&&(this.res=this.calResolution(this.mapExtent,this.viewportSize,this.options.fitTo))}var bbox=require("geojson-bbox"),extend=require("extend"),converter=require("./converter.js");function valueAt(obj,path){return path.split(".").reduce(function(prev,cur,i,arr){if(prev.hasOwnProperty(cur))return prev[cur];throw new Error(arr.slice(0,i+1).join(".")+" is not a valid property path")},obj)}GeoJSON2SVG.prototype.calResolution=function(extent,size,fitTo){var xres=(extent.right-extent.left)/size.width,extent=(extent.top-extent.bottom)/size.height;if(fitTo){if("width"===fitTo.toLowerCase())return xres;if("height"===fitTo.toLowerCase())return extent;throw new Error('"fitTo" option should be "width" or "height" ')}return Math.max(xres,extent)},GeoJSON2SVG.prototype.convert=function(geojson,options){var extent,resetExtent=!1,opt=(!this.res&&this.mapExtentFromGeojson&&(resetExtent=!0,extent=bbox(geojson),this.coordinateConverter&&(extent=function(extent,converter){var leftBottom=converter([extent[0],extent[1]]),converter=converter([extent[2],extent[3]]);return[...leftBottom,...converter]}(extent,this.coordinateConverter)),this.mapExtent={left:extent[0],bottom:extent[1],right:extent[2],top:extent[3]},this.res=this.calResolution(this.mapExtent,this.viewportSize,this.options.fitTo)),extend(!0,{},this.options,options||{})),svgElements=[];if("FeatureCollection"==geojson.type)for(var i=0;i<geojson.features.length;i++)svgElements=svgElements.concat(this.convertFeature(geojson.features[i],opt));else if("Feature"==geojson.type)svgElements=this.convertFeature(geojson,opt);else if("GeometryCollection"==geojson.type)for(i=0;i<geojson.geometries.length;i++)svgElements=svgElements.concat(this.convertGeometry(geojson.geometries[i],opt));else{if(!converter[geojson.type])throw new Error("Geojson type not supported.");svgElements=this.convertGeometry(geojson,opt)}return resetExtent&&(this.res=null,this.mapExtent=null),opt.callback&&opt.callback.call(this,svgElements),svgElements},GeoJSON2SVG.prototype.convertFeature=function(feature,options){var arr;if(feature||feature.geometry)return(options=extend(!0,{},this.options,options||{})).attributes&&options.attributes instanceof Array?(arr=options.attributes,options.attributes=arr.reduce(function(sum,property){if("string"==typeof property){var key=property.split(".").pop();try{val=valueAt(feature,property)}catch(e){val=!1}val&&(sum[key]=val)}else if("object"==typeof property&&property.type&&property.property)if("dynamic"===property.type){var val,key=property.key||property.property.split(".").pop();try{val=valueAt(feature,property.property)}catch(e){val=!1}val&&(sum[key]=val)}else"static"===property.type&&property.value&&(sum[property.property]=property.value);return sum},{})):options.attributes=options.attributes||{},(arr=options.attributes.id||feature.id||(feature.properties&&feature.properties.id?feature.properties.id:null))&&(options.attributes.id=arr),this.convertGeometry(feature.geometry,options)},GeoJSON2SVG.prototype.convertGeometry=function(geom,options){var opt,paths;if(converter[geom.type])return options=(opt=extend(!0,{},this.options,options||{})).output||"svg",paths=converter[geom.type].call(this,geom,this.res,{x:this.mapExtent.left,y:this.mapExtent.top},opt),"svg"==options.toLowerCase()?paths.map(function(path){return function(path,type,attributes,opt){var key,svg={},pointAsCircle=!(!opt||!opt.hasOwnProperty("pointAsCircle"))&&opt.pointAsCircle;"Point"!=type&&"MultiPoint"!=type||!pointAsCircle?(svg={d:path},"Polygon"!=type&&"MultiPolygon"!=type||svg["fill-rule"]):(svg.cx=path.split(",")[0],svg.cy=path.split(",")[1],svg.r=opt&&opt.r?opt.r:"1");for(key in attributes)svg[key]=attributes[key];return svg}(path,geom.type,opt.attributes,opt)}).map(function(json){return function(json,type,opt){var key,opt=!(!opt||!opt.hasOwnProperty("pointAsCircle"))&&opt.pointAsCircle,ele="<path";"Point"!=type&&"MultiPoint"!=type||!opt||(ele="<circle");for(key in json)ele+=" "+key+'="'+json[key]+'"';return ele+="/>"}(json,geom.type,opt)}):paths;throw new Error("Geojson type not supported.")},module.exports={GeoJSON2SVG:GeoJSON2SVG}},{"./converter.js":5,extend:2,"geojson-bbox":3}]},{},[1])(1)});

@@ -14,4 +14,4 @@ var dataURLPoly = './data/countries.geo.json';

panzoom(svgMap)
var convertor = geojson2svg(
{
var convertor = new GeoJSON2SVG(
{
viewportSize: {width:800,height:800},

@@ -18,0 +18,0 @@ attributes: {

@@ -27,10 +27,20 @@ // countries data taken from https://github.com/johan/world.geo.json

// covert wgs84 data to Web Mercator projection
var geojson = reproject.reproject(
var geojsonWebMerc = reproject.reproject(
geojson,'EPSG:4326','EPSG:3857',proj4.defs);
//render on svg
// calculate geojson data extent
var extent = bbox(geojsonWebMerc)
// get map svg element
var svgMap = document.getElementById('map');
var convertor = geojson2svg({ viewportSize: {width:800,height:800}});
// initiate GeoJSON2SVG
var convertor = new GeoJSON2SVG({
viewportSize: {width:800,height:800},
mapExtent: {
left: extent[0], right: extent[2],
bottom: extent[1], top: extent[3]
}
});
// render feature based on population
var svgElements = [];
geojson.features
geojsonWebMerc.features
.filter( function(f) {

@@ -46,3 +56,3 @@ return f.properties.population > 50000000; })

});
geojson.features
geojsonWebMerc.features
.filter( function(f) {

@@ -49,0 +59,0 @@ return f.properties.population <= 50000000; })

@@ -13,4 +13,4 @@ var dataURLPoly = './data/countries.geo.json';

var svgMap = document.getElementById('map');
var convertor = geojson2svg(
{
var convertor = new GeoJSON2SVG(
{
viewportSize: {width:800,height:800},

@@ -17,0 +17,0 @@ attributes: {

{
"name": "geojson2svg",
"version": "1.3.6",
"version": "2.0.0",
"description": "Converts geojson to svg/path string given svg viewport size and maps extent.",
"main": "src/main.js",
"types": "src/main.d.ts",
"main": "src/index.js",
"types": "src/index.d.ts",
"scripts": {
"test": "mocha",
"build-debug": "browserify src/main.js --debug --standalone geojson2svg | exorcist dist/geojson2svg.js.map > dist/geojson2svg.js",
"build-min": "browserify src/main.js --standalone geojson2svg | uglifyjs -c > dist/geojson2svg.min.js",
"build-debug": "browserify ./for-browserify.js --debug --standalone GeoJSON2SVG | exorcist dist/geojson2svg.js.map > dist/geojson2svg.js",
"build-min": "browserify ./for-browserify.js --standalone GeoJSON2SVG | uglifyjs -c > dist/geojson2svg.min.js",
"build": "npm run build-debug && npm run build-min",
"changelog": "auto-changelog --commit-limit=false && git add ./CHANGELOG.md && git commit --amend",
"watch:readme": "markserv README.md",
"release:patch": "npm version patch && npm run changelog",

@@ -30,6 +31,7 @@ "release:minor": "npm version minor && npm run changelog",

"dependencies": {
"extend": "^3.0.2",
"geojson-bbox": "^0.0.1",
"multigeojson": "~0.0.1"
},
"devDependencies": {
"@types/geojson": "^7946.0.10",
"auto-changelog": "^2.3.0",

@@ -41,8 +43,15 @@ "browserify": "~17.0.0",

"jsdom": "^18.1.1",
"mocha": "^9.1.4",
"mocha": "^10.1.0",
"parse-svg-path": "~0.1.2",
"pre-commit": "^1.2.2",
"proj4": "^2.9.0",
"standard-version": "^9.3.2",
"uglify-js": "^3.13.3",
"watchify": "^4.0.0"
},
"overrides": {
"markserv": {
"livereload": "0.9.3"
}
}
}
# geojson2svg
Converts geojson to svg string given svg viewport size and maps extent. geojson2svg can be used client side (in the browser) or server side (with NodeJs).
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) or server side (with Node.js).
Check [world map](https://rawgit.com/gagan-bansal/geojson2svg/master/examples/world.html), [SVG scaled map](https://rawgit.com/gagan-bansal/geojson2svg/master/examples/world-scaled.html) and [color coded map](https://rawgit.com/gagan-bansal/geojson2svg/master/examples/world-pop.html) examples to demonstrate that its very easy to convert geojson into map.
Check [world map](https://rawgit.com/gagan-bansal/geojson2svg/master/examples/world.html), [SVG scaled map](https://rawgit.com/gagan-bansal/geojson2svg/master/examples/world-scaled.html) and [color coded map](https://rawgit.com/gagan-bansal/geojson2svg/master/examples/world-pop.html) examples to demonstrate that its very easy to convert GeoJSON into map.
## Installation
Using in node.js or with browserify
```
npm install geojson2svg
```
For including in html page standard way, download file dist/geojson2svg.min.js
```html
<script type="text/javascript" src="path/to/geojson2svg.min.js"></script>
```
This creates a global variable 'geojson2svg'
🛠 [Installation](#-installation)
:car: [Usage](#car-usage)
:popcorn: [Basic Example](#popcorn-basic-example)
🔌 [API](#-api)
✈️ [Migration from 1.x to 2.x](#-migration-from-1x-to-2x)
📌 [Important points](#-important-points)
📋 [Changelog](#-changelog)
🪪 [License](#-license)
🔗 [Related useful articles](#-related-useful-articles)
geojson2svg is also available on [cdnjs](https://cdnjs.com/libraries/geojson2svg) and can be included like:
```html
<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/geojson2svg/x.x.x/geojson2svg.min.js"></script>
```
## 🛠 Installation
* Using in node.js
```
npm install geojson2svg
```
* For including in html page, download the build file [./dist/geojson2svg.min.js](https://raw.githubusercontent.com/gagan-bansal/geojson2svg/master/dist/geojson2svg.min.js)
```html
<script type="text/javascript" src="path/to/geojson2svg.min.js"></script>
```
This creates a global variable 'GeoJSON2SVG' as a Class.
## Usage
Using in node.js or with browserify
```javascript
var geojson2svg = require('geojson2svg');
var converter = geojson2svg(options);
var svgStrings = converter.convert(geojson,options);
```
Using in browser standard way
```
var converter = geojson2svg(options);
var svgStrings = converter.convert(geojson,options);
```
* geojson2svg is also available on [cdnjs](https://cdnjs.com/libraries/geojson2svg) and can be included like:
```html
<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/geojson2svg/x.x.x/geojson2svg.min.js"></script>
```
### Basic Example
## :car: Usage
* Using with node.js
With ES6
```javascript
import {GeoJSON2SVG} from 'geojson2svg';
const converter = new GeoJSON2SVG(options);
const svgStrings = converter.convert(geojson, options);
```
With CommonJS
```javascript
const {GeoJSON2SVG} = require('geojson2svg');
const converter = new GeoJSON2SVG(options);
const svgStrings = converter.convert(geojson, options);
```
* Usage in browser:
```
const converter = new GeoJSON2SVG(options);
const svgStrings = converter.convert(geojson,options);
```
## :popcorn: Basic Example
```javascript
var geojson2svg = require('geojson2svg');
const {GeoJSON2SVG} = require('geojson2svg');
var converter = geojson2svg({
attributes: ['properties.foo', 'properties.bar', 'properties.baz']
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
});
var svgStr = converter.convert({
const geojsonData = {
type: 'FeatureCollection',
features: [{
type: 'Feature',
geometry: {type: 'LineString', coordinates: [[0,0], [1000,1000]]},
properties: {foo: 'fooVal-1', bar: 'barVal-1', baz: 'bazVal-1'}
id: 'pt-1',
geometry: {type:'Point',coordinates:[50, 50]},
properties: {foo: 'val-1', class: 'point-tree'}
}, {
type: 'Feature',
geometry: {type: 'LineString', coordinates: [[10,10], [100,100]]},
properties: {foo: 'fooVal-2', bar: 'barVal-2'}
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="M128,128 128.00638801979818,127.99361198020182" foo="fooVal-1" bar="barVal-1" baz="bazVal-1"/>',
'<path d="M128.00006388019798,127.99993611980202 128.00063880197982,127.99936119802018" foo="fooVal-2" bar="barVal-2"/>'
]
// 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.
**convert** function returns an array of SVG elements' strings.
Now svg strings 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](https://github.com/gagan-bansal/parse-svg) or with any other parser. Read more about SVG string conversion to DOM Element [here](https://stackoverflow.com/a/3642265/713573).
## ✈️ Migration from 1.x to 2.x
```shell
npm install parse-svg
```
or include in your html file
```html
<script type="text/javascript" src="path/to/parse-svg.min.js"></script>
```
Simple way to convert svgStrings to svg elements
* Default export as a function is removed. Now `geojson2svg` exports class `GeoJSON2SVG`.
With 1.x
```javascript
const geojson2svg = require('geojson2svg');
const converter = geojson2svg(options);
```
Now with 2.x
```javascript
// With ES6
import {GeoJSON2SVG} from 'geojson2svg';
const converter = new GeoJSON2SVG(options);
const svgStrings = converter.convert(geojson, options);
// With CommonJS
const {GeoJSON2SVG} = require('geojson2svg');
const converter = new GeoJSON2SVG(options);
```
* Default value of `mapExtent` in 1.x was Web Mercator projection's full extent. In 2.x if `mapExtent` is not provided the `mapExtentFromGeoJSON` is considered to be true, that means the extent of the input data is considered as `mapExtent`.
* 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 the `mapExtent` as [Web Mercator extent](https://gis.stackexchange.com/a/280022/12962)
## 🔌 API
### Initializing the instance
```javascript
var parseSVG = require('parse-svg')
var svgElements = svgStrings.map(function(svgString) {
return parseSVG(svgString)
})
const converter = new GeoJSON2SVG(options);
```
### Options
Here are all options available for initializing the instance.
* **viewportSize** is object containing width and height in pixels. Default viewportSize values are:
```
{
width: 256,
height: 256
}
```
* **mapExtent:** {"left": coordinate, "bottom": coordinate, "right": coordinate, "top": coordinate}. Coordinates should be in same projection as of geojson. Default maps extent are of Web Mercator projection (EPSG:3857). Default extent values are:
```
{
left: -20037508.342789244,
right: 20037508.342789244,
bottom: -20037508.342789244,
top: 20037508.342789244
}
```
* **output:** 'svg'|'path' default is 'svg'
'svg' - svg element string is returned like ```'<path d="M0,0 20,10 106,40"/>'```
* **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. <ins>**NOTE: If `mapExtent` is not defined, the parameter `mapExtentFromGeojson` is considered `true`.**</ins>
'path' - path 'd' value is returned ```'M0,0 20,10 106,40'``` a linestring
* **mapExtentFromGeojson:** boolean, if true `mapExtent` is calculated from GeoJSON data that is passed in `.convert` function.
* **fitTo** 'width' | 'height' Fit ouput svg map to width or height.
* **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.
* **coordinateCoverter:** '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:
``` { "pointAsCircel": true } ```
output SVG string would be:
* **precision** a number, precision of output svg coordinates. Default is false.
```'<cirlce cx="30" cy="40" r="1" />'```
* **r:** radius of point SVG element
* **explode:** true | false, default is false. Should multigeojson be exploded to many svg elements or not.
* **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

@@ -142,11 +185,14 @@

Note: If a feature does not have value at the mentioned path then the attribute key would not be attached to svg string and even error would not be thrown.
**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.
* **pointAsCircle:** true | false, default is false. For point geojson return circle element for option:
``` { "pointAsCircel": true } ```
output svg string would be:
* **explode:** true | false, default is false. Should multigeojson be exploded to many SVG elements or not.
```'<cirlce cx="30" cy="40" r="1" />'```
* **r:** radius of point svg element
* **callback:** function, accept function that will be called on every geojson conversion with output string as one input variable e.g:
* **precision** number, precision of output SVG coordinates. Default is false.
* **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 linestring
* **callback:** function, accept function that will be called on every GeoJSON conversion with output string as one input variable e.g:
```

@@ -160,5 +206,10 @@ { "callback": function(svgString) {

The options **'attributes'**, **'r'** and **'callback'** can also be given in **convert** function
```
var svgStrings = converter.convert(geojson,
### Instance method
`.convert(geojson, options)`
The options **'attributes'**, **'r'** and **'callback'** can also be given in **convert** function's option. Example:
```javascript
let svgStrings = convertor.convert(geojson,
{

@@ -169,61 +220,39 @@ "attributes": ...,

}
);
```
## 📌 Important points
**mapExtent** is critical option default are the extents of Web Mercator projection ('EPSG:3857') or also known as Spherical Mercator. This projection is used by many web mapping sites (Google / Bing / OpenStreetMap). In case your source data is in geographic coordinates, it can be converted on the fly to Web Mercator Projection using [reproject-spherical-mercator](https://github.com/geosquare/reproject-spherical-mercator) or [reproject](https://github.com/perliedman/reproject) or [proj4js](https://github.com/proj4js/proj4js). Check my [world map](https://github.com/gagan-bansal/geojson2svg/blob/master/examples/world.html) example for detail.
* **mapExtent** is critical option. Usually your data would would be in [WGS84](https://en.wikipedia.org/wiki/World_Geodetic_System) (World Geodetic System) and unit as degree decimal for latitudes and longitude. Spatial reference system code for this is "EPSG:4326". To show the geographic data on two dimensional plane (paper or HTML page) the coordinates need to be projected. The usual choice is 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 [reproject-spherical-mercator](https://github.com/geosquare/reproject-spherical-mercator) or [reproject](https://github.com/perliedman/reproject) or [proj4js](https://github.com/proj4js/proj4js). Check [world map](https://github.com/gagan-bansal/geojson2svg/blob/master/examples/js/world.js) example for detail.
**Assigning id to SVG path**
* **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.id` or `feature.id`. Another way is explicitly specify the `id` attributes in `.convert` method, pass id along with attributes like `converter.convert(feature, {attributes: {id:'foo-1', class: 'bar'}})`. Preference order is: first as `id` key in attributes then `feature.id` and last `feature.properties.id`.
There are three ways for doing this. First and second, `.converter` reads it from `feature.properties.id` or `feature.id`. Third way, pass id along with attributes like `converter.convert(feature, {attributes: {id:'foo-1', class: 'bar'}})`. Preference order is first as id key in attributes then feature.id and last feature.properties.id.
* **Converting SVG string to HTML DOM element**, the SVG strings returned by `convert` method 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](https://github.com/gagan-bansal/parse-svg) or with any other parser. Read more about SVG string conversion to DOM Element [here](https://stackoverflow.com/a/3642265/713573) or [here](https://stackoverflow.com/a/24109000/713573). The usage of 'parse-svg' is as follows:
### Examples
Converts geojson LineString to svg element string:
```
var converter = geojson2svg(
{
viewportSize: {width: 200, height: 100},
mapExtent: {left: -180, bottom: -90, right: 180, top: 90},
output: 'svg'
}
);
var svgStrings = converter.convert(
{type:'LineString',coordinates:[[10,10],[15,20],[30,10]]}
);
//svgStrings: ['<path d="M105.55555555555556,44.44444444444444 108.33333333333333,38.888888888888886 116.66666666666666,44.44444444444444" />']
```
Converts geojson Polygon to svg path data 'd' string:
```
var converter = geojson2svg(
{
viewportExtent: {width: 200, height: 100},
mapExtent: {left: -180, bottom: -90, right: 180, top: 90},
output: 'path'
}
);
var pathData = converter.convert(
{
"type": "Polygon",
"coordinates": [
[[30, 10], [40, 40], [20, 40], [10, 20], [30, 10]]
]
}
);
// pathData: ['M116.66666666666666,44.44444444444444 122.22222222222221,27.77777777777778 111.11111111111111,27.77777777777778 105.55555555555556,38.888888888888886 116.66666666666666,44.44444444444444Z']
```
```shell
npm install parse-svg
```
or include in your html file
```html
<script type="text/javascript" src="path/to/parse-svg.min.js"></script>
```
Simple way to convert svgStrings to SVG elements
Check my blog [maps-on-blackboard](http://maps-on-blackboard.github.io/tag/geojson2svg/) for more detailed examples.
## Developing
Once you run
```javascript
var parseSVG = require('parse-svg');
var svgElements = svgStrings.map(parseSVG);
```
```npm install```
## 📋 Changelog
Check [here](https://github.com/gagan-bansal/geojson2svg/blob/master/CHANGELOG.md)
then for running test
## 🪪 License
```npm run test```
This project is licensed under the terms of the [MIT license](https://github.com/gagan-bansal/geojson2svg/blob/master/LICENSE).
to create build
## 🔗 Related useful articles
```npm run build```
##License
This project is licensed under the terms of the MIT license.
* [CSS-TRICKS: SVG Properties and CSS](https://css-tricks.com/svg-properties-and-css/)
* [MDN SVG Tutorial: SVG and CSS](https://developer.mozilla.org/en-US/docs/Web/SVG/Tutorial/SVG_and_CSS)
* [JENKOV SVG Tutorial: SVG and CSS - Cascading Style Sheets](https://jenkov.com/tutorials/svg/svg-and-css.html#css-attributes)
* Check my blog [maps-on-blackboard](http://maps-on-blackboard.github.io/tag/geojson2svg/) for more detailed examples using `geojson2svg`.
//converter.js
var multi = require('multigeojson');
function getCoordString(coords,res,origin, precision) {
function getCoordString(coords,res,origin, precision, opt) {
//origin - svg image origin
var convertedCoords = coords.map(function(coord) {
if (opt.coordinateConverter) {
coord = opt.coordinateConverter(coord);
}
return [(coord[0] - origin.x)/res, (origin.y - coord[1])/res];

@@ -31,3 +35,3 @@ });

? opt.pointAsCircle : false;
var coords = getCoordString([geom.coordinates],res,origin,opt.precision);
var coords = getCoordString([geom.coordinates],res,origin,opt.precision, opt);
if (pointAsCircle) {

@@ -53,3 +57,3 @@ return [coords];

function lineString(geom,res,origin,opt) {
var coords = getCoordString(geom.coordinates,res,origin,opt.precision);
var coords = getCoordString(geom.coordinates,res,origin,opt.precision, opt);
var path = 'M'+ coords;

@@ -68,3 +72,3 @@ return [path];

var mainStr,holes,holeStr;
mainStr = getCoordString(geom.coordinates[0],res,origin,opt.precision);
mainStr = getCoordString(geom.coordinates[0],res,origin,opt.precision, opt);
if (geom.coordinates.length > 1) {

@@ -76,3 +80,3 @@ holes = geom.coordinates.slice(1,geom.coordinates.length);

for(var i=0;i<holes.length; i++) {
path += ' M' + getCoordString(holes[i],res,origin,opt.precision);
path += ' M' + getCoordString(holes[i],res,origin,opt.precision, opt);
}

@@ -79,0 +83,0 @@ }

@@ -7,3 +7,3 @@ 'use strict';

var testData = require('./testdata.js');
var expect = require('chai').expect;
var {expect, assert} = require('chai');
var parsePath = require('parse-svg-path');

@@ -15,20 +15,43 @@ var jsdom = require('jsdom');

var precision = testData.precision;
describe(testData.desc+ ': .convert()', function() {
var geojson2svg = require('../src/main.js');
var converter = geojson2svg(testData.options);
testData.geojsons.forEach(function(data) {
it(data.type+ ' {output: "path",explode: false,r:2}',function() {
var {GeoJSON2SVG} = require('../src/index.js');
describe('Test geojson2svg class and instance', function () {
it('GeoJSON2SVG is function',function () {
expect(typeof GeoJSON2SVG === 'function').to.be.true;
});
var converter = new GeoJSON2SVG(testData.options);
it('converter is an instance of GeoJSON2SVG', function () {
assert.instanceOf(converter, GeoJSON2SVG);
});
it("converter has method convert", function () {
assert.isFunction(converter.convert);
});
it("converter has method convertFeature", function () {
assert.isFunction(converter.convertFeature);
});
it("converter has method convertGeometry", function () {
assert.isFunction(converter.convertGeometry);
});
});
describe("Test all geojson types for 'convert' function", function() {
var converter = new GeoJSON2SVG(testData.options);
testData.geojsons.forEach(function(data) {
it(data.type+ ' {output: "path",explode: false,r:2}',function() {
var options = {output:'path'};
options = merge(options,testData.options);
var actualPaths = converter.convert(data.geojson,options);
testPath(actualPaths,data.path,data.geojson.type,precision);
});
it(data.type + ' {output: "svg",explode: false,r:2}',function() {
var actualSVGs = converter.convert(data.geojson,testData.options);
testSVG(actualSVGs,data.svg,data.geojson.type,precision);
});
var actualPaths = converter.convert(data.geojson,options);
assertPath(actualPaths,data.path,data.geojson.type,precision);
});
it(data.type + ' {output: "svg",explode: false,r:2}',function() {
var actualSVGs = converter.convert(data.geojson,testData.options);
assertSVG(actualSVGs,data.svg,data.geojson.type,precision);
});
});
});
describe("Test all options of 'convert' function", function() {
var converter = new GeoJSON2SVG(testData.options);
it('Point while output svg as Circle', function() {
var expSVGs = [ '<circle cx="128.00031940098992" cy="127.99968059901009" r="2"/>' ]
var converter = geojson2svg(testData.options);
var converter = new GeoJSON2SVG(testData.options);
var actualSVGs = converter.convert(

@@ -54,3 +77,3 @@ {type:'Point',coordinates:[50,50]},

var expSVGs = ['<path d="M105.556,44.444 108.333,38.889 116.667,44.444"/>'];
var converter = geojson2svg(testData.options);
var converter = new GeoJSON2SVG(testData.options);
var actualSVGs = converter.convert(geojson, {precision: 3});

@@ -64,3 +87,3 @@ expect(actualSVGs).to.be.an('array');

{output:'path',explode:false});
testPath(actualPaths,testData.feature.path,
assertPath(actualPaths,testData.feature.path,
testData.feature.geojson.type,

@@ -76,3 +99,3 @@ precision);

});
testSVG(actualSVGs,testData.feature.svg,
assertSVG(actualSVGs,testData.feature.svg,
testData.feature.geojson.geometry.type,

@@ -85,3 +108,3 @@ precision);

{output:'path',explode:true});
testPath(actualPaths,testData.feature.path_explode,
assertPath(actualPaths,testData.feature.path_explode,
testData.feature.geojson.type,

@@ -99,3 +122,3 @@ precision);

});
testSVG(actualSVGs,testData.feature.svg,
assertSVG(actualSVGs,testData.feature.svg,
testData.feature.geojson.geometry.type,

@@ -112,3 +135,3 @@ precision);

for(var i=0; i < expPaths.length; i++) {
testPath([actualPaths[i]],[expPaths[i]],
assertPath([actualPaths[i]],[expPaths[i]],
testData.featureCollection.geojson.features[i].geometry.type,precision);

@@ -118,3 +141,3 @@ }

it('Polygon fit to width', function() {
var converter2 = geojson2svg(
var converter2 = new GeoJSON2SVG(
{

@@ -130,3 +153,3 @@ viewportSize: {width: 300, height: 100},

testData['Polygon fit to width'].geojson);
testSVG(
assertSVG(
actualData,

@@ -137,12 +160,8 @@ testData['Polygon fit to width'].svg,

});
it('Default vieport size and default maps extent.', function() {
var converter = geojson2svg();
var actualOutput = converter.convert(testData['Default values'].geojson);
testSVG(actualOutput, testData['Default values'].svg,
testData['Default values'].geojson.type, precision);
});
it('add attributes to svg based on each feature properties:', function() {
var converter = geojson2svg(
{attributes: ['properties.foo', 'properties.bar', 'properties.baz']})
it('Add attributes to svg based on each feature properties:', function() {
var converter = new GeoJSON2SVG({
mapExtent: testData.mercatorExtent,
attributes: ['properties.foo', 'properties.bar', 'properties.baz']
})
var svgStr = converter.convert({

@@ -174,5 +193,6 @@ type: 'FeatureCollection',

it('add attributes to svg based on each feature properties and static attributes also:', function() {
var converter = geojson2svg(
{attributes: [
it('Add attributes to svg based on each feature properties and static attributes also:', function() {
var converter = new GeoJSON2SVG({
mapExtent: testData.mercatorExtent,
attributes: [
{

@@ -190,3 +210,3 @@ property: 'properties.foo',

}]
})
});
var svgStr = converter.convert({

@@ -219,5 +239,8 @@ type: 'FeatureCollection',

it('add given attributes in options to all svg elements: '
it('Add given attributes in options to all svg elements: '
+ 'pass attributes in constructor', function() {
var converter = geojson2svg({attributes: {class: 'foo'}});
var converter = new GeoJSON2SVG({
mapExtent: testData.mercatorExtent,
attributes: {class: 'foo'}
});
var output = converter.convert(

@@ -229,5 +252,8 @@ {type:'LineString', coordinates: [[0,0], [1000,1000]]});

});
it('add given attributes in options to all svg elements: '
it('Add given attributes in options to all svg elements: '
+ 'pass attributes in .convert', function() {
var converter = geojson2svg({attributes: {class: 'foo',id: 'foo-1'}});
var converter = new GeoJSON2SVG({
mapExtent: testData.mercatorExtent,
attributes: {class: 'foo',id: 'foo-1'}
});
var output = converter.convert(

@@ -242,4 +268,7 @@ {type:'LineString', coordinates: [[0,0], [1000,1000]]},

});
it('add id to svg: as feature.id', function() {
var converter = geojson2svg({attributes: {class: 'foo'}});
it('Add id to svg: as feature.id', function() {
var converter = new GeoJSON2SVG({
mapExtent: testData.mercatorExtent,
attributes: {class: 'foo'}
});
var output = converter.convert({

@@ -255,4 +284,7 @@ type: 'Feature',

});
it('add id to svg: as feature.properties.id', function() {
var converter = geojson2svg({attributes: {class: 'foo'}});
it('Add id to svg: as feature.properties.id', function() {
var converter = new GeoJSON2SVG({
mapExtent: testData.mercatorExtent,
attributes: {class: 'foo'}
});
var output = converter.convert({

@@ -268,6 +300,37 @@ type: 'Feature',

});
it('Extent from geojson', function () {
var converter = new GeoJSON2SVG({
mapExtentFromGeojson: true
});
var actualData = converter.convert(
testData['Extent from geojson'].geojson);
assertSVG(
actualData,
testData['Extent from geojson'].svg,
testData['Extent from geojson'].geojson.type,
precision);
});
it('coordinateConverter options', function () {
const proj4 = require('proj4');
const forward = proj4('WGS84', 'EPSG:3857').forward;
var converter = new GeoJSON2SVG({
mapExtentFromGeojson: true,
viewportSize: {width: 800, height: 60},
fitTo: 'width',
coordinateConverter: forward
});
var actualData = converter.convert(
testData['coordinateConverter option'].geojson);
assertSVG(
actualData,
testData['coordinateConverter option'].svg,
testData['coordinateConverter option'].geojson.type,
precision);
})
});
});
function testSVG(actualSVGs,expSVGs,type,precision) {
function assertSVG(actualSVGs,expSVGs,type,precision) {
expect(actualSVGs).to.be.an('array');

@@ -283,7 +346,7 @@ expect(actualSVGs.length).to.be.equal(expSVGs.length);

actPaths = actSVGEle.getAttribute('d');
testPath([actPaths],[expPaths],type,precision);
assertPath([actPaths],[expPaths],type,precision);
//}
}
function testPath(actualPaths,expPaths,type,precision) {
function assertPath(actualPaths,expPaths,type,precision) {
expect(actualPaths).to.be.an('array');

@@ -290,0 +353,0 @@ expect(actualPaths.length).to.be.equal(expPaths.length);

module.exports = {
desc: 'input data is goegraphic coordinates',
options: {

@@ -9,3 +8,8 @@ viewportSize: {width: 200, height: 100},

precision: 0.00000001,
mercatorExtent: {
left: -20037508.342789244,
right: 20037508.342789244,
bottom: -20037508.342789244,
top: 20037508.342789244
},
geojsons: [

@@ -214,3 +218,24 @@ { type: 'Point',

svg_explode: ['M138.2249984726979,123.15948293350895 140.91249847232382,118.26706092824489 146.9749984714799,118.78064836091235 147.4749984714103,122.59252437872642 143.1624984720106,124.3534713101955 138.2249984726979,123.15948293350895Z']
},
"Extent from geojson": {
type: "Extent from geojson",
geojson: {
type: 'Feature',
geometry: {
type: 'LineString',
coordinates: [
[10, 40], [40, 30], [20, 20], [30, 10]
]
}
},
svg: ['<path d="M0,0 256,85.33333333333333 85.33333333333333,170.66666666666666 170.66666666666666,256"/>']
},
"coordinateConverter option": {
type: "coordinateConverter option",
geojson: {
type:'LineString',
coordinates:[[-71, 41], [51, 51]]
},
svg: [ '<path d="M0,94.77680169959633 800,0"/>' ]
}
}

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc