npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

svgeomin

v0.1.3

Published

Create compact map SVGs and GeoJson subsets

Readme

npm version license CDN CDN

Key features

svgeomin has a strong focus on SVG application – most importantly creating lightweight SVG map assets. However, it also comes with some handy geoJson helpers to reduce a given data source to the actually needed geo features.

  • topology aware Ramer-Douglas-Peucker polygon simplification for Geojson supsets and SVG
  • removal of small sub features e.g islands or exclaves
  • advanced SVG pathData minification (e.g relative commands)
  • multiple projection modes: Web Mercator, Miller, Behrmann, Equi-rectangular
  • property based filtering of geodata feautures for subset creation
  • convert/revert SVG to geoJson
  • add markers to SVG using common lon/lat coordinates

TOC

The challenges of geodata (why another library)

Geojsons are most often massive – 10K+ of coordinates are rather the lower end of the scale. For reasonably sized SVG assets, geometry simplifications are rather mandatory. But when we apply these (Ramer Douglas Peucker, Visvalingam etc) for each feature (e.g country border) individually we often get gaps between polygon edges.

Advanced map/geodata or data visualization libraries – e.g d3 – have developed sophisticated solutions such as the TopoJson superset for specifying shared polygon edges to allow for predictable simplification results.

However, these libraries are more focused on map specific use cases and highly complex. Besides, they often provide only basic control over the SVG output – resulting in rather huge markup sizes.

To put it differently:

svgeomin might be interesting if …

  • you just need a convenient way to create compact svg maps
  • shrink a massive geojson to used features

not very suitable for you if …

  • if you're already a d3 or map pro
  • your focus is on interactive map applications

Usage

Svgeomin can be loaded as IIFE or ESM module. For testing you can require it via CDN e.g.

CDN

IIFE

<script src="https://cdn.jsdelivr.net/npm/potrace-plus@latest/dist/potrace-plus.min.js"></script>

ESM

import { svgFromGeo } from "https://cdn.jsdelivr.net/npm/svgeomin@latest/dist/svgeomin.esm.min.js";

Todos

  • Node.js is currently not supported as some helpers require DOM Parser API.

Basic example: render from src URL

Svgeomin allows multiple input formats:

  • geojson URL (requires async function call)
  • stringified geojson
  • parsed geojson object
// ESM import – not needed for IIFE build
import { svgFromGeo } from "./dist/svgeomin.esm.js";

// static geojson asset
let geoDataUrl = 'geoData.geojson';

// needs async when loading from URL
(async () => {
    // process
    let svGeo = await svgFromGeo(geoDataUrl);

    // render/append to HTML target element
    let target = document.getElementById('svgeoWrap');

    svGeo.render(target)
})();

See basic.html.

With options: Filter features and simplify

You can filter geodata features by property names e.g to show only a selection of countries. Also, you can apply multiple options e.g for Ramer-Douglas-Peucker simplification.

// ESM import – not needed for IIFE build
import { svgFromGeo } from "./dist/svgeomin.esm.js";

// static geojson asset
let geoDataUrl = 'geoData.geojson';

// needs async when loading from URL
(async () => {

    let options = {
        scale: 10000,

        // remove small areas e.g island
        minArea: 1,

        // filter to these features
        features: ['germany', 'switzerland', 'austria'],

        // filter properties
        properties: ['name'],
    }

    // process
    let svGeo = await svgFromGeo(geoDataUrl, options);

    // render/append to HTML target element
    let target = document.getElementById('svgeoWrap');

    svGeo.render(target)
})();

See demo/options.html.

Options

| parameter | type | description | default/values | |--|--|--|--| |features|array|features to filter|empty| |properties|array|properties to include in filtered Geojson and SVG output|empty| |exclude|array|exclude feature items by property values|empty| |scale|number|scale to reasonable coordinate space to avoid floating points and tiny SVG viewBoxes|10000| |simplify|number|threshold for RDP simplification ~in km|0| |minArea|number|remove small feautes e.g islands or exclaves by km² threshold (sloppy area approximation) |0| |split|number/Boolean|create path el for each sub poly e.g islands |0| |meta|number/Boolean|add meta for original geodata reference in SVG |0| |classPre|string|CSS classname prefix for SVG elements |'svgeomin'| |css|string|append CSS <style> element to SVG |''| |cssInline|string|main svg inline css |''| |projection|string |changes projection method | 'mercator' (Web Mercator). mercator,miller, equirectangular (Plate carrée), behrmann |projection method. See wikipedia: List of map projections | |markers|array| add map markers to SVG |empty| |marker params|| || |lon|number| longitude |0| |lat|number| latitude |0| |icon|string| Add custom SVG icon: Accepts SVG markup or pathData strings |'' – inserts default marker icon| |bb|array| controls alignment of custom icon: x, y, width, height |[0,0,24,24]| |width|number| controls size of marker icon |24| |styles|object/string| Add CSS properties for markers: CSS string or object. When using objects you need to camleCase property names (e.g strokeWidth) |''| |meta|object| adds properties as data-attributes to marker element |0|

Topology aware simplification

When applying polygon simplification algorithms (e.g Ramer Douglas Peucker) on adjacent/neighboring polygons we often get gaps between shapes.

To prevent this we first analyze the topology of all filtered features to detect shared polygon arcs to ensure a consistent edge simplification.

SVGEO object and API methods

Once you parsed the geoJson via svgFromGeo() an object is created which allows further processing:

// init object
const SVGEO = await svgFromGeo(geoDataUrl, options);

// retrieve properties directly from object
let { svg, bb, x, y, bbGeo, scale, size } = SVGEO;

// render
SVGEO.render(svgeoWrap)

// get GeoJson
let geojsonOptions = {
    // round to decimals
    decimals:4,

    // name for feature collection
    name: 'svgeomin',

    // properties to include
    properties:[],
}
let geojson = SVGEO.getGeoJson(geojsonOptions)

/**
 * get object or data 
 * URLs for download
 */
let urlOptions = {
    // return svg or json
    data='svg',

    //round to decimals
    decimals=3

    // return dataURL or object URL
    dataUrl=true,

    // add width and height attributes for SVG
    addDimensions=true

    // add SVG xlink namespace for legacy apps
    addXlink=false

}
let dataUrl = SVGEO.getUrl(urlOptions)

erm, but I still see tiny gaps?

  1. The aforementioned topology simplification takes for granted the GeoData itself doesn't have any gaps
  2. if you notice thin hairlines in SVG rendering: it is simply due to sub-pixel rendering. Anti-aliasing will inevitable produce tiny gaps due to pixel-grid fitting problems.

Quick fix

  • Apply a thin stroke to your paths
  • disable anti-aliasing via SVG shape-rendering attribute: shape-rendering="crispEdges" should do the trick.

Demos

Credits

Recommendations (tools and documentations)

Related projects