geochart in d3.js - javascript

I'm looking for some guidance or an example how to do a geochart in d3.js.
I need something like this one in google charts, and turning to d3.js since I need some customization. So far the closest d3.js sample I found is this but the code is very long there and I am hoping to find something simpler.

Are you looking for a choropleth map? Here's a recent example in 28 lines of code.
This example uses the default projection, d3.geo.albersUsa, which is a composite projection for the United States including Alaska, Hawaii and Puerto Rico. If you want to change the visible region, you probably also want to change the projection; d3.geo.albers is good for choropleth maps because it is equal-area. The albers projection lets you set the origin so that you can focus on a specific part of the global, and all projections allow you to specify scale and translate to position the map on-screen.
If you want to display a world map, I'd also take a look at the ongoing development of the extended projections plugin. This adds a number of useful map projections, particularly for world maps, such as the Winkel Tripel. The next release of D3 will also include some exciting new features such as three-dimensional rotation for any projection (including antemeridian cutting; try dragging this example), adaptive resampling and improved clipping.
As for coloring the choropleth, you can of course color geographic features however you like by redefining the "fill" style as a function of data.

With all due respect to #mbostock and his answer, I thought I would add some additional resources for anyone coming across this question.
The example in the link provided by #Yaron Naveh appears to be a Mercator projection. You can find out more about d3.js' Mercator projection facilities in the d3.js API. #mbostock has also been kind enough to create blocks/gists for each of the projections in the API (click on the projection thumbnail image for the example). Here are the links to a simple Mercator projection block/gist.
Regarding the "The Art of Asking - How are you feeling?" link, here is a little code to go with what #mbostock said about coloring using the fill style as a function of data. In this example, I am simply picking the unicode value for the first character of the country's name in the JSON file and making a CSS color from that value using "steelblue" (#4682B4 = 4620980) as a sort of seed (you will probably want to calculate shades/tints).
d3.json("readme.json", function(collection) {
d3.select("svg").selectAll("path")
.data(collection.features)
.enter().append("path")
.attr("d", d3.geo.path().projection(d3.geo.mercator()))
.style("fill", function(d) { return '#'+Math.floor(d.properties.name.charCodeAt(0)/100*4620980).toString(16); });
});
You can check out the full example here as a block/gist.
(#mbostock - Thank you for such a great tool!)

Related

Generating a continuous interpolated surface from point data with Mapbox GL JS

I'm relatively new to Mapbox and its GL JS Library, but so far have been really impressed at its capabilities.
I'm currently working with a dataset of approximately 100,000 points and am trying to devise a way of quickly generating/visualising a continuous interpolated surface within the convex hull of the dataset I have (essentially trying to generate something that's as fast/responsive as the heatmap function, but looking to interpolate from the point data values rather than spatial density).
The documentation for the heatmap functionality discusses this exact scenario:
Among maps you'll find on the web, there are two common categories of
heatmaps: those that encourage the user to explore dense point data,
and those that interpolate discrete values over a continuous surface,
creating a smooth gradient between those points. The latter is less
common and most often used in scientific publications or when a
phenomenon is distributed over an area in a predictable way. For
example, your town may only have a few weather stations, but your
favorite weather app displays a smooth gradient of temperatures across
the entire area of your town. For your local weather service, it is
reasonable to assume that, if two adjacent stations report different
temperatures, the temperature between them will transition gradually
from one to the next.
But then proceeds to explain this is less common and there's no documentation/example provided for this type of application.
At this stage I've tried converting the points to voronoi cell polygons and colour coding by data value (a nearest neighbour approach to visualising), but the render seems to struggle with 100,000 points at lower zoom levels (0 through 8). Does anyone know if it's possible to create a fast-rendering surface interpolation from point values? Any examples would be fantastic.
The Mapbox Delaunator library is a very fast JavaScript library for Delaunay triangulation of 2D points. d3-delaunay and d3-geo-voronoi are both based off of this library. You could use these libraries and then display the results on your map via a custom style layer.
Looks like what you are trying to do is some sort of Spatial Interpolation.
Here is a summary of popular methods typically used for this purpose.
https://michaelminn.net/tutorials/r-spatial-interpolation/

Create a polygon around each point in geojson from geojson

Creating a map similar to the one found here:
https://www.plantmaps.com/interactive-california-2012-usda-plant-zone-hardiness-map.php
Have all the data needed.
Create polygons around each one without distance inbetween. No overlapping or similar.
Drawing it all by hand on geojson.io, seems impossible.
I want to create polygons around each [point] and make sure there is no distance between them.
What you're describing here is a tessellation. Depending on your data, you might opt for a regular tessellation (i.e. creating a grid of squares or hexagons, paying a modicum of attention to the units of your coordinate system) or the well-known-among-GIS-people Voronoi tessellation. Note that a Voronoi tessellation created over a regular grid of points will result in a regular grid of polygons.
There are plenty of tools for Voronoi tessellations. For javascript and GeoJSON, my tool of choice would be turf.js's voronoi module.
Here are some things to consider:
creating polygon from a point is simple enough. For example you use the point as the center of a regular polygon and devide 2PI by the number of sides and step through the points to create the polygon. But, what is the radius? That depends on the projection you are using. I happen to use OpenLayers and really like this map control. It's default projection it EPSG:3857. So, the coordinates are already in meters - so easy. But if your points are in long/lat then you have to do some math. it may be easier to transform to a different projection temporarily. An opensource library that is really nice for gis calculations if you need one is Turf.
You mentioned also about having non-overlapping polygons? Well, in this case you will have a lot of gaps if you use regular polygons. To have non-overlapping polygons with, as you put it no distance between them is an interesting constraint. Now you are dealing with different shaped polygons. And an algorithm for handling that is pretty intense. I know that MapInfo GIS has a feature for adjusting polygons to be non-overlapping. But, in a JavaScript environment with GeoJSON, you are probably talking about server side logic for this.
That map you are looking at looks like it is using Leaflet with svg overlays.

Plot geometry of longitude and latitude coordinates using javascript

I have longitude and latitude coordinates which represent different types of geometry shapes (point, multi-point, polygon, multi-polygon and line string etc) that are stored in MongoDB. I'd like plot them (say each shape as a layer) using JavaScript. Map is not needed as a background although these coordinates represent building etc in the real world. I understand there are calculations as such are involved to convert coordinates to x and y on graph/canvas but not sure where to begin tbh. I'm very new to GIS and JavaScript so go easy on me please. I know this question sounds a bit vague but bottom line is I have coordinates that represent real world elements and want to plot them without a map background. I'd appreciate advises and suggestions. Many thanks.
The easiest way to do it is to use a Javascript mapping library such as OpenLayers or Leaflet. You could also do it with D3, although should you want to make your map more full-featured later, it will be much easier with a library that was designed for that type of thing.
If you are storing your data in Mongo as GeoJSON (GeoJSON website), you can add it to OpenLayers as a GeoJSON layer.
Disclaimer- My opinions might be slightly biased because I used to work for Boundless

how save leaflet draw 's data custom toGeoJSON?

leaflet use FeatureGroup() for edit. and I want to save data use toGeoJSON.but circle,marker... have point info only.
{"type":"FeatureCollection","features":[{"type":"Feature","properties":{},"geometry":{"type":"Point","coordinates":[118.49561691284181,31.87595414652557]}},{"type":"Feature","properties":{},"geometry":{"type":"Point","coordinates":[118.5268591952,31.848500597]}}]}
I need save more info.how?
Strictly speaking saving this kind of data "to GeoJSON" is not possible because simply GeoJSON does not support circles.
GeoJSON supports the following geometry types:
Point, LineString, Polygon, MultiPoint, MultiLineString,
MultiPolygon, and GeometryCollection.
The old 2008 GeoJSON spec says nothing about circles http://geojson.org/geojson-spec.html
and neither the new one (august 2016) https://www.rfc-editor.org/rfc/rfc7946
If you want to save a point and its radius to represent a circle you need to make a format of your own, but this of course will not work out-of-the-box with leaflet's geojson layergroup.
Edit: seems some people went down that road already so you may wanna check this out:
https://github.com/Leaflet/Leaflet.draw/issues/390
They saving the radius in the properties of GeoJSON and extended the GeoJSON layergroup to work with that. A bit hacky, geojson spec goes down the drain, but it seems to accomplish what you want.
Another possibility is to convert your circles to polygons with an acceptable amount of nodes, then saving that polygon in GeoJSON.

D3 + Leaflet with Albers USA Projection

I'd like to use D3 + Leaflet with the Albers USA projection.
I used Mike Bostock's D3 + Leaflet demonstration as a starting point (found here: http://bost.ocks.org/mike/leaflet/). I'm not sure how to properly use the Albers USA projection. I've encountered a couple problems while trying to figure out how to do this:
I'm not sure how to make Leaflet use the Albers USA projection. I think I might be able to do it using the Proj4Leaflet plugin, but I've been unable to find the parameters that I need to pass to it when creating the CRS that specify Albers USA. I've found some potential configuration strings on spatialreference.org, but I don't know what to specify for origin or resolutions and haven't found anything out there that explains it.
D3's Albers USA projection is returning null for some points in the collection and for the bounds. I'm using the us-states.json file that Mike Bostock used. I found the explanation for that here: https://github.com/mbostock/d3/issues/1287. "[...]it will now return null for points outside the composite projection’s clip extent, since such points would not be displayed when using the projection stream". I'm not sure how to proceed from here. Should I be using a different data set?
If anyone has any advice on how to proceed, I'd greatly appreciate it!
You may have two separate questions, so here are brief answers to both -
1.) Your source data doesn't need to be in Albers-US (which isn't strictly speaking a projection anyway - AK and HI aren't in Mexico) in order to bring it into Leaflet. Here's the US States dataset as GeoJSON, in geographic coordinates: https://gist.github.com/wboykinm/6979292
2.) Whatever the projection of the source data, Leaflet only renders in the Google Mercator projection (The projection you see in the example you started from). If you absolutely must have Albers US, it shouldn't really be a pan-able/zoomable map for reasons of context distortion. Just use Mike's D3 example for a static map: http://bl.ocks.org/mbostock/6320825
If you're determined to make a slippy map for Leaflet using Albers US, who am I to stop you? But that process would require a.) moving of feature geometry in a GIS program, and b.) fooling Tilemill into using the wrong projection as it creates tiles for you to use in Leaflet. Not a recommended course of action.
I would also be remiss if I didn't mention that you can always make your D3 graphic zoomable with d3.behavior.zoom()

Categories