D3 Draw Circle on Map
This chapter looks at D3'southward approach to rendering geographic information.
As an example, the globe below is drawn using D3. A GeoJSON file is loaded and D3 is used to project the geographic information and depict it on a Canvass chemical element:
D3's approach differs to and so chosen raster methods such as Leaflet and Google Maps. These pre-render map features every bit image tiles and these are loaded from a web server and pieced together in the browser to form a map.
Typically D3 requests vector geographic information in the grade of GeoJSON and renders this to SVG or Sail in the browser.
Raster maps oft expect more like traditional print maps where a lot of detail (due east.thousand. place names, roads, rivers etc.) can exist shown without an impact on operation. However, dynamic content such as animation and interaction is more easily implemented using a vector approach. (Information technology'southward too quite mutual to combine the two approaches.)
D3 mapping concepts
The iii concepts that are central to understanding map cosmos using D3 are:
- GeoJSON (a JSON-based format for specifying geographic data)
- projections (functions that convert from latitude/longitude co-ordinates to x & y co-ordinates)
- geographic path generators (functions that catechumen GeoJSON shapes into SVG or Canvas paths)
GeoJSON
GeoJSON is a standard for representing geographic data using the JSON format and the full specification is at geojson.org.
Here's a typical GeoJSON object:
In the to a higher place object there's a FeatureCollection containing an array of 3 features:
- Africa
- Australia
- the city of Timbuktu
Each feature consists of geometry (simple polygons in the example of the countries and a point for Timbuktu) and properties.
Properties can contain any information about the characteristic such every bit name, id, and other data such as population, GDP etc.
D3 takes intendance of almost of the particular when rendering GeoJSON and then yous merely demand a basic understanding of GeoJSON to get started with D3 mapping.
Projections
A project function takes a longitude and latitude co-ordinate (in the course of an array [lon, lat]
) and transforms it into an x and y co-ordinate:
Project mathematics tin go quite complex only fortunately D3 provides a large number of project functions.
For example you can create an equi-rectangular projection function using:
Nosotros'll look at projections in more item later.
Geographic path generators
A geographic path generator is a function that takes a GeoJSON object and converts it into an SVG path cord. (In fact, it'due south just some other type of shape generator.)
You tin create a generator using the method .geoPath
and configure it with a project function:
As usual with shape generators the generated path string is used to fix the d
attribute on an SVG path
element.
Putting it all together
Given some GeoJSON, a project role and a geographic path generator you can create a basic map:
geoJson.features
is an assortment of features. This array is joined to path
elements. The d
attribute is prepare using the function geoGenerator
. This receives a characteristic every bit its first parameter and outputs a path cord.
The last line may look like magic just is the equivalent of:
.attr('d', function(d) { return geoGenerator(d); });
In this case the parameter d
is a GeoJSON feature.
To go along things simple the GeoJSON in the above example uses just a few co-ordinates to define the country boundaries.
The above instance shows the essence of creating maps using D3 and I recommend spending time to understand each concept (GeoJSON, projections and geo generators) and how they fit together.
Now that we've covered the nuts we'll look at each concept in more than detail.
GeoJSON
GeoJSON is a JSON-based structure for specifying geographic information. More often than not information technology's converted from shapefile data (a geospatial vector information format widely used in the GIS field) using tools such as mapshaper, ogr2ogr, shp2json or QGIS.
A pop source of world map shapefiles is Natural Earth and if starting out I recommend trying out mapshaper for importing shapefiles and exporting as GeoJSON. It can also filter by backdrop (eastward.m. if yous wanted to filter countries by continent). For a more than in depth await at conversion look at Mike Bostock's Let's Make a Map tutorial.
You tin create maps without understanding the GeoJSON specification in minute item considering tools such as mapshaper and D3 practice such a practiced job of abstracting away the particular. However, if you lot did desire to understand GeoJSON in greater depth I recommend checking out the official specification.
So far nosotros've embedded a GeoJSON object in our instance files. In practice the GeoJSON would be in a carve up file and loaded using an ajax request. We embrace requests in more detail in the requests affiliate only for the remainder of this chapter nosotros'll load a GeoJSON file using:
Information technology's worth mentioning TopoJSON which is some other JSON based standard for describing geographic information and tends to result in significantly smaller file sizes. Information technology requires a scrap more work to use, and we don't encompass it in this affiliate. Notwithstanding for further data check out the documentation.
Projections
There are numerous (if not infinite) means of converting (or 'projecting') a bespeak on a sphere (east.g. the world) to a betoken on a apartment surface (eastward.g. a screen) and people take written endless articles (such as this one) on the pros and cons of different projections.
In short in that location is no perfect project as every projection will distort shape, area, distance and/or direction. Choosing a projection is a example of choosing which property you don't want to exist distorted and accepting that in that location'll be distortion in the other backdrop (or choose a projection that strives for a balanced approach). For case, if it's of import that the size of countries are represented accurately then choose a projection that strives to preserve area (probably to the cost of shape, distance and direction).
D3 has a number of core projections that should cover most employ cases:
-
geoAzimuthalEqualArea
-
geoAzimuthalEquidistant
-
geoGnomonic
-
geoOrthographic
-
geoStereographic
-
geoAlbers
-
geoConicConformal
-
geoConicEqualArea
-
geoConicEquidistant
-
geoEquirectangular
-
geoMercator
-
geoTransverseMercator
Some projections preserve area (e.g. geoAzimuthalEqualArea
& geoConicEqualArea
), others altitude (e.g. geoAzimuthalEquidistant
& geoConicEquidistant
) and others relative angles (eastward.g. geoEquirectangular
& geoMercator
). For a more than in depth discussion of the pros and cons of each projection try resources such every bit Carlos A. Furuti's Map Projection Pages.
The filigree below shows each core projection on a world map together with a longitude/breadth grid and equal radius circles.
Projection functions
A projection function takes input [longitude, breadth]
and outputs a pixel co-ordinate [ten, y]
.
Be conscientious to note the order of longitude and latitude in the above array!
You're free to write your ain projection functions but much easier is to ask D3 to brand ane for you. To practise this cull a project method (due east.g. d3.geoAzimuthalEqualArea
), call it and it'll return a projection part:
The core projections have configuration functions for setting the post-obit parameters:
scale | Scale factor of the project |
center | Projection eye [longitude, breadth] |
interpret | Pixel [10,y] location of the projection eye |
rotate | Rotation of the project [lambda, phi, gamma] (or [yaw, pitch, roll]) |
The precise meaning of each parameter is dependent on the mathematics behind each project but broadly speaking:
- scale specifies the scale factor of the projection. The college the number the larger the map.
- center specifies the center of project (with a
[lon, lat]
array) - interpret specifies where the centre of projection is located on the screen (with a
[x, y]
array) - rotate specifies the rotation of the projection (with a
[λ, φ, γ]
array) where the parameters stand for to yaw, pitch and ringlet, respectively:
For instance y'all can create and configure a projection function such that Timbuktu is centred in a 960x500 map using:
To get a feel for how each parameter behaves use the project explorer beneath. The (equal radius) circles and filigree allow you lot to assess the projection'due south distortion of area and angle.
.invert()
You can convert a pixel co-ordinate [x, y]
to a longitude/latitude array using the projection'due south .invert()
method:
Fitting
Given a GeoJSON object, a projection'southward .fitExtent()
method sets the project'southward scale and interpret such that the geometry fits within a given bounding box:
The first statement of .fitExtent
is an assortment containing 2 coordinates: the tiptop left signal ([x, y]
) of the bounding box and the size ([width, height]
) of the bounding box. The second argument is a GeoJSON object.
In the example below the canvas chemical element has a lite grey background and the bounding box into which we're fitting the geoJSON is shown as a dotted outline. The following lawmaking is used to fit the geometry within the bounding box:
If your bounding box's top left corner is at [0, 0]
you can omit the top left coordinate and but supply the width and height:
Geographic path generators
A geographic path generator is a function that transforms GeoJSON into an SVG path string (or into canvass element calls):
Yous create the generator using d3.geoPath()
and must configure it'south projection type:
You lot can at present utilize the generator to help create an SVG or canvass map. The SVG option is a bit easier to implement, particularly when it comes to user interaction (because upshot handlers and hover states tin can be added).
The canvass approach requires a chip more than work but is typically faster to render (and more than memory efficient).
Rendering SVG
To return an SVG map you:
- join a GeoJSON features array to SVG
path
elements - update each
path
element'sd
attribute using the geographic path generator
For instance:
geoJson.features
is an assortment of features. This array is joined to path
elements. The d
aspect is ready using the function geoGenerator
. This receives a characteristic as its first parameter and outputs a path string.
Rendering to canvass
To render to a canvas element y'all pass the canvas
DOM chemical element into the generator's context
method:
The
.node
method returns the showtime DOM element of a pick.
You then brainstorm a canvas path (using context.beginPath()
) and call geoGenerator
which volition produce the necessary canvass calls:
Lines and arcs
The geographic path generator is clever enough to distinguish between polygonal (typically for geographic areas) and point (typically for lon/lat locations) features. Every bit can be seen in the above examples information technology renders polygons as line segments and points as arcs.
Yous can set the radius of the circles using .pointRadius()
:
Path geometry
The geographic path generator tin can also be used to compute the expanse (in pixels), centroid, bounding box and path length (in pixels) of a projected GeoJSON feature:
This example shows the expanse and length of a hovered path. It as well draws the path'south centroid and bounding box:
Shapes
If you need to add lines and/or circles to a map you tin can add together features to the GeoJSON.
Lines tin can be added as a LineString feature and will be projected into neat-arcs (i.e. the shortest distance across the surface of the globe).
Hither's an example where a line is added between London and New York:
Circumvolve features can be generated using d3.geoCircle()
. This creates a circle generator which returns a GeoJSON object representing a circumvolve.
Typically the centre ([lon, lat]
) and the radius (in degrees) are set:
A GeoJSON grid of longitude and latitude lines (known equally a graticule) can be generated using d3.graticule()
. This creates a graticule generator which returns a GeoJSON object representing the graticules:
(See the official documentation for detailed information on graticule configuration.)
Here'due south an case where a line, a circle and graticules are added to a map:
Spherical geometry
There's a scattering of D3 methods that may come in useful from time to fourth dimension. The get-go of these .geoArea()
, .geoBounds()
, .geoCentroid()
, .geoDistance()
and geoLength()
are similar to the path geometry methods described higher up only operate in spherical space.
Interpolation
The d3.geoInterpolate()
method creates a function that accepts input between 0 and 1 and interpolates betwixt 2 [lon, lat]
locations:
geoContains
If you lot're using a canvas
chemical element to render your geometry yous don't have the luxury of being able to add consequence handlers onto SVG path
elements. Instead you tin check whether mouse or touch events occur inside the boundary of a characteristic. You tin can do this using d3.geoContains
which accepts a GeoJSON feature and a [lon, lat]
assortment and returns a boolean:
Source: https://www.d3indepth.com/geographic/
0 Response to "D3 Draw Circle on Map"
Post a Comment