{"id":1030,"date":"2018-02-24T13:00:21","date_gmt":"2018-02-24T13:00:21","guid":{"rendered":"http:\/\/chewett.co.uk\/blog\/?p=1030"},"modified":"2018-08-09T23:07:52","modified_gmt":"2018-08-09T22:07:52","slug":"overlaying-geo-data-leaflet-version-1-3-d3-js-version-4","status":"publish","type":"post","link":"https:\/\/chewett.co.uk\/blog\/1030\/overlaying-geo-data-leaflet-version-1-3-d3-js-version-4\/","title":{"rendered":"Overlaying geo data with Leaflet Version 1.3 and D3.js Version 4"},"content":{"rendered":"<p><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" data-attachment-id=\"1436\" data-permalink=\"https:\/\/chewett.co.uk\/blog\/1431\/simple-d3-js-version-5-data-binding-and-updating-example-and-code\/d3_overlaying_geo_data_with_leaflet\/\" data-orig-file=\"https:\/\/i0.wp.com\/chewett.co.uk\/blog\/wp-content\/uploads\/2018\/08\/d3_overlaying_geo_data_with_leaflet.jpg?fit=800%2C300&amp;ssl=1\" data-orig-size=\"800,300\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"d3_overlaying_geo_data_with_leaflet\" data-image-description=\"\" data-image-caption=\"\" data-medium-file=\"https:\/\/i0.wp.com\/chewett.co.uk\/blog\/wp-content\/uploads\/2018\/08\/d3_overlaying_geo_data_with_leaflet.jpg?fit=300%2C113&amp;ssl=1\" data-large-file=\"https:\/\/i0.wp.com\/chewett.co.uk\/blog\/wp-content\/uploads\/2018\/08\/d3_overlaying_geo_data_with_leaflet.jpg?fit=678%2C254&amp;ssl=1\" class=\"aligncenter size-full wp-image-1436\" src=\"https:\/\/i0.wp.com\/chewett.co.uk\/blog\/wp-content\/uploads\/2018\/08\/d3_overlaying_geo_data_with_leaflet.jpg?resize=678%2C254\" alt=\"\" width=\"678\" height=\"254\" srcset=\"https:\/\/i0.wp.com\/chewett.co.uk\/blog\/wp-content\/uploads\/2018\/08\/d3_overlaying_geo_data_with_leaflet.jpg?w=800&amp;ssl=1 800w, https:\/\/i0.wp.com\/chewett.co.uk\/blog\/wp-content\/uploads\/2018\/08\/d3_overlaying_geo_data_with_leaflet.jpg?resize=300%2C113&amp;ssl=1 300w, https:\/\/i0.wp.com\/chewett.co.uk\/blog\/wp-content\/uploads\/2018\/08\/d3_overlaying_geo_data_with_leaflet.jpg?resize=768%2C288&amp;ssl=1 768w, https:\/\/i0.wp.com\/chewett.co.uk\/blog\/wp-content\/uploads\/2018\/08\/d3_overlaying_geo_data_with_leaflet.jpg?resize=50%2C19&amp;ssl=1 50w\" sizes=\"auto, (max-width: 678px) 100vw, 678px\" \/><\/p>\n<p>In this post I describe how you can overlay Geo Data onto a leaflet map with D3.js.<\/p>\n<p><!--more--><\/p>\n<h2>Combining Leaflet and D3 and objectives<\/h2>\n<p>There are a number of tutorials online on how to overlay Geodata with D3.js. However, I couldn&#8217;t find any of these that worked for the most recent version of D3.js and Leaflet. They were all fundamentally broken. This post goes into the details of overlaying simple circles on a leaflet map.<\/p>\n<p>Here I am using the latest (as of writing) versions of Leaflet and D3.js. These are V1.3 and V4.13.0 for leaflet and D3.js respectively.<\/p>\n<h2>Setting up Leaflet<\/h2>\n<p>First I am going to set up Leaflet and set some defaults up. Once this is done I will be able to set up D3 and start overlaying data.<\/p>\n<p>First Leaflet needs to be imported and the CSS needs to be loaded. Here I have used cdnjs to load the library but this can be a local copy if preferred.<\/p>\n<pre>&lt;link rel=\"stylesheet\" href=\"https:\/\/cdnjs.cloudflare.com\/ajax\/libs\/leaflet\/1.3.1\/leaflet.css\"\/&gt;\r\n&lt;script src=\"https:\/\/cdnjs.cloudflare.com\/ajax\/libs\/leaflet\/1.3.1\/leaflet.js\"&gt;&lt;\/script&gt;<\/pre>\n<p>To draw a leaflet map you must first create an element to draw into. In the body of my HTML I create a div to hold the data and style its width and height.<\/p>\n<pre>&lt;div id=\"map\" style=\"width: 600px; height: 600px\"&gt;&lt;\/div&gt;<\/pre>\n<p>Once I have created the map div I can start creating the map using JavaScript.<\/p>\n<pre>var map = L.map('map').setView([51.505548, -0.075316], 16);\r\nmapLink = L.tileLayer('http:\/\/{s}.tile.openstreetmap.org\/{z}\/{x}\/{y}.png').addTo(map);<\/pre>\n<p>Above I create a map centering on the coordinates <code>51.505548, -0.075316<\/code>.\u00a0In the second line I add a tile layer using the open street map tiling and add it to the map. These two lines then create a scrollable map on the page in the map div.<\/p>\n<p>Now I have my leaflet scrollable map and can start to add geo data to it.<\/p>\n<h2>Setting up D3 and the SVG layer to draw to<\/h2>\n<p>Now I have my leaflet map I can start to add D3 and elements to the map.<\/p>\n<p>In the head element I need to include the d3 source so I add the following line to the page.<\/p>\n<pre>&lt;script src=\"https:\/\/cdnjs.cloudflare.com\/ajax\/libs\/d3\/4.13.0\/d3.min.js\"&gt;&lt;\/script&gt;<\/pre>\n<p>D3.js operates on a SVG element so I need to add a SVG to the Leaflet map. Using Leaflet I ask it to create\u00a0a\u00a0SVG element and add it to the map.\u00a0This can be done with the following code.<\/p>\n<pre>var svgLayer = L.svg();\r\nsvgLayer.addTo(map);<\/pre>\n<p>By default Leaflet adds an initial group element inside this SVG so I can access both the SVG and the group using the following D3.js.<\/p>\n<pre>var svg = d3.select(\"#map\").select(\"svg\");\r\nvar g = svg.select('g');<\/pre>\n<p>Now I have access to the SVG and the group I can start to work with the data.<\/p>\n<h2>Loading data and Drawing to the SVG<\/h2>\n<p>For this demonstration, I have a json file with some coordinates that I am going to highlight on the map.<\/p>\n<pre>[\r\n  {\"coordinate\":[51.506532, -0.074624]},\r\n  {\"coordinate\":[51.504452, -0.076028]},\r\n  {\"coordinate\":[51.505548, -0.075316]},\r\n  {\"coordinate\":[51.508109, -0.076061]},\r\n  {\"coordinate\":[51.506019, -0.073639]}\r\n]<\/pre>\n<p>These could have names and more information to display on the map but for this example I am going o merely circle the locations.<\/p>\n<p>To load this data I am going to use the D3.js loading functionality.<\/p>\n<pre>d3.json(\"london.json\", function(pointsOfInterest) {\r\n    \/\/code here\r\n});<\/pre>\n<p>Here this will load <code>london.json<\/code>\u00a0asynchronously and once it has loaded it will call the callback. The contents of the file will be json decoded and stored in the variable <code>pointsOfInterest<\/code>.\u00a0The following code lives in this callback.<\/p>\n<p>Leaflet uses a custom object to hold latitude and longitude data, <code>L.LatLng<\/code>. So once my data has loaded I add this data to the pointsOfInterest object.<\/p>\n<pre>pointsOfInterest.forEach(function(d) {\r\n    d.latLong = new L.LatLng(d.coordinate[0], d.coordinate[1]);\r\n});<\/pre>\n<p>Once I have this in a form Leaflet will understand I start by creating the circles using D3.js.<\/p>\n<pre>var feature = g.selectAll(\"circle\")\r\n    .data(pointsOfInterest)\r\n    .enter().append(\"circle\")\r\n    .style(\"stroke\", \"black\")\r\n    .style(\"opacity\", .4)\r\n    .style(\"fill\", \"blue\")\r\n    .attr(\"r\", 20);<\/pre>\n<p>Here I take the data from my <code>pointsOfInterest<\/code>\u00a0object and create a circle for each data item. At the moment this is just adding the elements to the group inside the SVG. This is not yet placing it on the correct place on the map.<\/p>\n<p>Once I have the circles created I create a function that will place them in the correct location.<\/p>\n<pre>function drawAndUpdateCircles() {\r\n    feature.attr(\"transform\",\r\n        function(d) {\r\n            var layerPoint = map.latLngToLayerPoint(d.latLong);\r\n            return \"translate(\"+ layerPoint.x +\",\"+ layerPoint.y +\")\";\r\n        }\r\n    )\r\n}<\/pre>\n<p>This code adds the transform attribute to each of the circles. This is used to move the circle in the correct place on the map. However before the circle can be overlaid I need to work out where on the screen it needs to be placed.<\/p>\n<p>I have stored where to store the circles using latitude and longitude values. This needs to be transformed into a pixel location on screen. Leaflet provides a simple way of doing this with <code>map.latLngToLayerPoint(value)<\/code>. This returns an object with two properties, x and y. I then use these values to translate the location of the circles to the correct place on the map.<\/p>\n<p>The final piece of code draws the shapes on the map and attaches the above function to the <code>moveend<\/code> event.<\/p>\n<pre>drawAndUpdateCircles();\r\nmap.on(\"moveend\", drawAndUpdateCircles);<\/pre>\n<p>This means that every time that the map is moved or zoomed the location of the circles will be recalculated. Note this has changed compared to previous versions of Leaflet that required you to bind to the <code>viewreset<\/code> event.<\/p>\n<h2>Summary<\/h2>\n<p>Now I have created a Leaflet map and initialized the location. Once I had done this I initialised a SVG layer with Leaflet and targetted this with D3.js. Using D3.js I loaded json holding coordinate data and drew circles on the SVG. The final step was to create an update function which placed the circles on the correct location on the maps.<\/p>\n<p>The full code for this is available <a href=\"https:\/\/chewett.co.uk\/d3\/d3_and_leaflet\/\">on my website which includes a live example<\/a>.<\/p>\n<p>If you have any questions feel free to comment on the following blog post.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In this post I describe how you can overlay Geo Data onto a leaflet map with D3.js.<\/p>\n","protected":false},"author":1,"featured_media":1034,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_exactmetrics_skip_tracking":false,"_exactmetrics_sitenote_active":false,"_exactmetrics_sitenote_note":"","_exactmetrics_sitenote_category":0,"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2}},"categories":[98],"tags":[229,72,230,231,232,233],"class_list":["post-1030","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-software","tag-d3-js","tag-javascript","tag-leaflet","tag-open-street-maps","tag-osm","tag-svg"],"wppr_data":{"cwp_meta_box_check":"No"},"jetpack_publicize_connections":[],"jetpack_featured_media_url":"https:\/\/i0.wp.com\/chewett.co.uk\/blog\/wp-content\/uploads\/2018\/02\/d3_leaftlet_intro.jpg?fit=800%2C800&ssl=1","jetpack_shortlink":"https:\/\/wp.me\/p2toWX-gC","jetpack_sharing_enabled":true,"jetpack-related-posts":[{"id":1038,"url":"https:\/\/chewett.co.uk\/blog\/1038\/new-d3-js-part-website\/","url_meta":{"origin":1030,"position":0},"title":"New D3.js part of my website","author":"Chewett","date":"February 28, 2018","format":false,"excerpt":"This post talks about the new D3.js part of my website and what I plan to do with it. The website! I have added a link on the homepage of my website to the new D3.js section. Here you will be able to view all my D3.js projects and tutorials.\u2026","rel":"","context":"In &quot;Software&quot;","block_context":{"text":"Software","link":"https:\/\/chewett.co.uk\/blog\/category\/software\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/chewett.co.uk\/blog\/wp-content\/uploads\/2018\/02\/d3_on_website.jpg?fit=800%2C800&ssl=1&resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/chewett.co.uk\/blog\/wp-content\/uploads\/2018\/02\/d3_on_website.jpg?fit=800%2C800&ssl=1&resize=350%2C200 1x, https:\/\/i0.wp.com\/chewett.co.uk\/blog\/wp-content\/uploads\/2018\/02\/d3_on_website.jpg?fit=800%2C800&ssl=1&resize=525%2C300 1.5x, https:\/\/i0.wp.com\/chewett.co.uk\/blog\/wp-content\/uploads\/2018\/02\/d3_on_website.jpg?fit=800%2C800&ssl=1&resize=700%2C400 2x"},"classes":[]},{"id":1485,"url":"https:\/\/chewett.co.uk\/blog\/1485\/drawing-shapes-in-d3-js-version-5\/","url_meta":{"origin":1030,"position":1},"title":"Drawing shapes in D3.js Version 5","author":"Chewett","date":"September 5, 2018","format":false,"excerpt":"This post goes over the various D3.js symbols typically used for scatter plots. D3.js built-in symbols D3.js has a number of built-in symbols which can be used for any data visualisation needs. The most common use of these are\u00a0for points on scatter plots and similar graphs. It is important to\u2026","rel":"","context":"In &quot;Software&quot;","block_context":{"text":"Software","link":"https:\/\/chewett.co.uk\/blog\/category\/software\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/chewett.co.uk\/blog\/wp-content\/uploads\/2018\/08\/d3_v5_drawing_shapes.jpg?fit=800%2C800&ssl=1&resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/chewett.co.uk\/blog\/wp-content\/uploads\/2018\/08\/d3_v5_drawing_shapes.jpg?fit=800%2C800&ssl=1&resize=350%2C200 1x, https:\/\/i0.wp.com\/chewett.co.uk\/blog\/wp-content\/uploads\/2018\/08\/d3_v5_drawing_shapes.jpg?fit=800%2C800&ssl=1&resize=525%2C300 1.5x, https:\/\/i0.wp.com\/chewett.co.uk\/blog\/wp-content\/uploads\/2018\/08\/d3_v5_drawing_shapes.jpg?fit=800%2C800&ssl=1&resize=700%2C400 2x"},"classes":[]},{"id":1483,"url":"https:\/\/chewett.co.uk\/blog\/1483\/d3-js-version-5-scatterplot-with-shapes\/","url_meta":{"origin":1030,"position":2},"title":"D3.js version 5 Scatterplot with shapes","author":"Chewett","date":"September 15, 2018","format":false,"excerpt":"Today I write about\u00a0how you can create a scatter plot with different shapes in D3.js version 5. Aim of this tutorial This blog builds on Mike Bostocks\u00a0Scatterplot with shapes example and reworks it for D3.js version 5. This tutorial will focus on the changes needed to convert the original diagram\u2026","rel":"","context":"In &quot;Software&quot;","block_context":{"text":"Software","link":"https:\/\/chewett.co.uk\/blog\/category\/software\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/chewett.co.uk\/blog\/wp-content\/uploads\/2018\/08\/d3_v5_scatterplot_with_shapes-1.jpg?fit=800%2C800&ssl=1&resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/chewett.co.uk\/blog\/wp-content\/uploads\/2018\/08\/d3_v5_scatterplot_with_shapes-1.jpg?fit=800%2C800&ssl=1&resize=350%2C200 1x, https:\/\/i0.wp.com\/chewett.co.uk\/blog\/wp-content\/uploads\/2018\/08\/d3_v5_scatterplot_with_shapes-1.jpg?fit=800%2C800&ssl=1&resize=525%2C300 1.5x, https:\/\/i0.wp.com\/chewett.co.uk\/blog\/wp-content\/uploads\/2018\/08\/d3_v5_scatterplot_with_shapes-1.jpg?fit=800%2C800&ssl=1&resize=700%2C400 2x"},"classes":[]},{"id":1700,"url":"https:\/\/chewett.co.uk\/blog\/1700\/colour-scales-in-d3-version-5\/","url_meta":{"origin":1030,"position":3},"title":"Colour scales in D3 Version 5","author":"Chewett","date":"November 3, 2018","format":false,"excerpt":"Over the past versions in D3.js there have been a number of changes to how you can get a colour scale to use with your charting. This blog post explores what is available and how to use it. This blog post applies to D3.js version 5. Colour scales in D3.js\u2026","rel":"","context":"In &quot;Software&quot;","block_context":{"text":"Software","link":"https:\/\/chewett.co.uk\/blog\/category\/software\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/chewett.co.uk\/blog\/wp-content\/uploads\/2018\/11\/d3_colour_scales-1.jpg?fit=800%2C800&ssl=1&resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/chewett.co.uk\/blog\/wp-content\/uploads\/2018\/11\/d3_colour_scales-1.jpg?fit=800%2C800&ssl=1&resize=350%2C200 1x, https:\/\/i0.wp.com\/chewett.co.uk\/blog\/wp-content\/uploads\/2018\/11\/d3_colour_scales-1.jpg?fit=800%2C800&ssl=1&resize=525%2C300 1.5x, https:\/\/i0.wp.com\/chewett.co.uk\/blog\/wp-content\/uploads\/2018\/11\/d3_colour_scales-1.jpg?fit=800%2C800&ssl=1&resize=700%2C400 2x"},"classes":[]},{"id":2021,"url":"https:\/\/chewett.co.uk\/blog\/2021\/how-to-load-multiple-d3-versions-at-once\/","url_meta":{"origin":1030,"position":4},"title":"How to load multiple D3 versions at once","author":"Chewett","date":"March 2, 2019","format":false,"excerpt":"Today I am writing a short tutorial on how you can load multiple D3.js versions at once. Why you might want to load multiple D3 versions? Most of the time you will be using the same version of D3 for all visualisations on the page. However there may be cases\u2026","rel":"","context":"In &quot;Software&quot;","block_context":{"text":"Software","link":"https:\/\/chewett.co.uk\/blog\/category\/software\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/chewett.co.uk\/blog\/wp-content\/uploads\/2019\/02\/loading_multiple_d3_versions-1.jpg?fit=800%2C800&ssl=1&resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/chewett.co.uk\/blog\/wp-content\/uploads\/2019\/02\/loading_multiple_d3_versions-1.jpg?fit=800%2C800&ssl=1&resize=350%2C200 1x, https:\/\/i0.wp.com\/chewett.co.uk\/blog\/wp-content\/uploads\/2019\/02\/loading_multiple_d3_versions-1.jpg?fit=800%2C800&ssl=1&resize=525%2C300 1.5x, https:\/\/i0.wp.com\/chewett.co.uk\/blog\/wp-content\/uploads\/2019\/02\/loading_multiple_d3_versions-1.jpg?fit=800%2C800&ssl=1&resize=700%2C400 2x"},"classes":[]},{"id":1463,"url":"https:\/\/chewett.co.uk\/blog\/1463\/summary-of-mike-bostock-on-d3-selections\/","url_meta":{"origin":1030,"position":5},"title":"Summary of Mike Bostock on D3 selections","author":"Chewett","date":"August 25, 2018","format":false,"excerpt":"Today I talk about and link to Mike Bostock's post on D3 selections, in this he talks about the basic unit of d3, the selection. Who is Mike Bostock? Mike Bostock is one of the key developers of d3.js and worked for a number of years creating visualizations with this\u2026","rel":"","context":"In &quot;Software&quot;","block_context":{"text":"Software","link":"https:\/\/chewett.co.uk\/blog\/category\/software\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/chewett.co.uk\/blog\/wp-content\/uploads\/2018\/08\/d3_mike_post_selections.jpg?fit=800%2C800&ssl=1&resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/chewett.co.uk\/blog\/wp-content\/uploads\/2018\/08\/d3_mike_post_selections.jpg?fit=800%2C800&ssl=1&resize=350%2C200 1x, https:\/\/i0.wp.com\/chewett.co.uk\/blog\/wp-content\/uploads\/2018\/08\/d3_mike_post_selections.jpg?fit=800%2C800&ssl=1&resize=525%2C300 1.5x, https:\/\/i0.wp.com\/chewett.co.uk\/blog\/wp-content\/uploads\/2018\/08\/d3_mike_post_selections.jpg?fit=800%2C800&ssl=1&resize=700%2C400 2x"},"classes":[]}],"_links":{"self":[{"href":"https:\/\/chewett.co.uk\/blog\/wp-json\/wp\/v2\/posts\/1030","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/chewett.co.uk\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/chewett.co.uk\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/chewett.co.uk\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/chewett.co.uk\/blog\/wp-json\/wp\/v2\/comments?post=1030"}],"version-history":[{"count":8,"href":"https:\/\/chewett.co.uk\/blog\/wp-json\/wp\/v2\/posts\/1030\/revisions"}],"predecessor-version":[{"id":1439,"href":"https:\/\/chewett.co.uk\/blog\/wp-json\/wp\/v2\/posts\/1030\/revisions\/1439"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/chewett.co.uk\/blog\/wp-json\/wp\/v2\/media\/1034"}],"wp:attachment":[{"href":"https:\/\/chewett.co.uk\/blog\/wp-json\/wp\/v2\/media?parent=1030"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/chewett.co.uk\/blog\/wp-json\/wp\/v2\/categories?post=1030"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/chewett.co.uk\/blog\/wp-json\/wp\/v2\/tags?post=1030"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}