I am trying to optimize a little bit the SVG I am generating using the amazing D3js geo module.
I am using d3.geo.path
as the d
attribute generator for SVG paths:
path = d3.geo.path().projection(config.projection); // projection is initialized somewhere else
and then using it to render paths like this:
svg.selectAll(".country")
.data(countries)
.enter()
.insert("path", ".graticule")
.attr({
class: "country",
d: path
})
and the kind of path strings I am getting are like this one:
M713.601085,459.8780053259876L714.7443994399441,460.08170562468473L715.0310281028103,460.5903728431771L715.0310281028103...
As can be seen, some numbers are extremely long with too many decimals and not really useful at my current resolution, which clogs a little bit the DOM and makes it sluggish to debug these paths (there are also many, since it's a world map with lots of countries drawn on it).
So my first approach was creating this pathSimplified
wrapper for path
:
// Path simplified: take some decimals out of the 'd' string
pathSimplified = function (d) {
return path(d).replace(/(\.\d{4})\d+/g, '$1');
};
and then use it instead of path
:
//...
.attr({
class: "country",
d: pathSimplified
})
That works and now I get only 4 decimals for each value on the path string. Like this:
M713.6010,459.8780L714.7443,460.0817L715.0310,460.5903L715.0310...
My question is: can it be done in a better, less hackish way? It doesn't feel right to tweak the string after it's spit out by D3js's path
function and it would be nice to specify the rounding at some point on the path itself or the projection...
Your idea is good, simplifying a polyline helps, but you can certainly do it better than just truncating coordinates: algorithms for polyline semplification exist and might give you nicer results.
For example, take a look at the Ramer-Douglas-Peucker algorithm. It is implemented in libraries like Simplify.js(check the demo on that page out), which also allows you to adjust it with tolerance. You'll have to pass the line as an array of x/y coords, but I trust that isn't too complicated to do.
I also noticed that d3 geo projections allow for a precision parameter (like here), maybe there's something like that that you overlooked? In any case, simplifying coordinates on your own with simplify.js is usually always possible.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With