preface

This article mainly records how to draw the map with D3.js, and how to scale the map. It’s not so difficult to figure out the general process and steps.

The general flow chart is as follows:

Next, expand the article in the following order:

  • What is the GeoJSON
  • map
  • Zoom to monitor

This article uses version D3: V5.9.2

What is the GeoJSON

We’ll start with GeoJSON, which is the source of our map data.

Look directly at the introduction from Wikipedia

GeoJSON is an open standard format designed for representing simple geographical features, along with their non-spatial attributes. It is based on the JavaScript Object Notation (JSON).

The features include points (therefore addresses and locations), line strings (therefore streets, highways and boundaries), polygons (countries, provinces, tracts of land), and multi-part collections of these types. GeoJSON features need not represent entities of the physical world only; mobile routing and navigation apps, for example, might describe their service coverage using GeoJSON.

The following key points can be extracted from it:

  • Based on JSON format
  • Features saves map drawing information of points, lines and polygons

Wikipedia gives an example as follows (excerpt) :

{
  "type": "FeatureCollection"."features": [{"type": "Feature"."geometry": {
        "type": "Point"."coordinates": [102.0, 0.5]},"properties": {
        "prop0": "value0"}}, {"type": "Feature"."geometry": {
        "type": "LineString"."coordinates": [[102.0, 0.0], [103.0, 1.0], [104.0, 0.0], [105.0, 1.0]]}."properties": {
        "prop0": "value0"."prop1": 0.0}},......Copy the code

As you can see, the Features array stores drawing information. How is this drawing information drawn? Wikipedia also gives an example of controlling the type of drawing by Type and coordinates controlling points, paths, shapes.

This is just a few examples, but if you’re interested, go to Wikipedia.

In summary, we know what GeoJSON is.

Get GeoJSON

There are many ways to get GeoJSON using a search engine. Here domestic map data can use Ali DATAV’s map selector

DATAV – Map selector

In this article, choose the map of Beijing and download GeoJSON

map

Now we can start mapping. In order to facilitate learning, without making various requests and solving cross-domain problems, we directly copy the contents of GeoJSON into a separate JS file to set variables.

//BeijingGeo.js
const BeijingGEoJson = {
  type: "FeatureCollection".features: [{type: "Feature".properties: {
        adcode: 110101.name: "Dongcheng District".center: [116.418757.39.917544],... }Copy the code

Then we can begin in earnest


      
<html lang='en'>

<head>
    <meta charset='UTF-8'>
    <title></title>
    <script src=".. /d3_library/d3.js"></script>
    <! Put the BeijingGeoJson file as a JS object in a js file with the output variable BeijingGeoJson -->
    <script src=".. /source/js/BeijingGeo.js"></script>
</head>

<body>
    <svg class="chart">

    </svg>
</body>
<script>
    /** * Basic configuration */
    const svgWidth = 500;
    const svgHeight = 500;
    const padding = 30;

    const svg = d3.select(".chart")
        .attr("height", svgHeight)
        .attr("width", svgWidth);
</script>
</html>
Copy the code

Projection Settings

Projection Transforms a spherical polyhedral figure into a planar polyhedral figure, such as a map of the earth.

The Projections transform polygonal geometry to planar polygonal geometry

The following types of projections are provided in D3:

  • Azimuthal
  • I’m making a Composite.
  • Conic (cone)
  • Cylindrical

In this paper, we use Mercator projection, which is the most widely used projection in our daily life. Baidu Map and Google Map are all using Mercator projection.

The Mercator projection is a normal axis equiangular cylindrical projection, and the API in D3 is d3.geomercator ().

Now let’s get the projection and configure it

const projection = d3.geoMercator() // Mercator projection
                     .center([someValue, someValue])  // Chained,.center([longitude, latitude]) sets the center of the map
                     .scale([someValue])   //.scale([value]) sets the map scale
                     .translate([someValue, someValue]) //.translate([x,y]) Sets the offset
Copy the code

But because of the different GeoJSON data, configuring this projection is relatively cumbersome. Fortunately, D3 provides the meguiar. FitExtent API, which simply passes in the upper-left coordinate point, lower-right coordinate point, and GeoJSON, and draws the map in the center of a given canvas.

const x0 = padding;
const y0 = padding;
const x1 = svgWidth - padding * 2;
const y1 = svgHeight - padding * 2;
const projection = d3.geoMercator().fitExtent(
    [
        [x0, y0],
        [x1, y1],
    ], BeijingGeoJson);
Copy the code

Geographic Path Generator

Getting the geographic path generation function is simple and takes only one line of code

const pathGenerator = d3.geoPath()
                        .projection(projection); // Configure the projection
Copy the code

After the data binding, we use this function to draw the PATH element in SVG to outline the map graphics

Data binding, using the geographic path generator function to draw maps

Next comes the drawing step. Maps in SVG are drawn with the path element

const mapPath = svg.selectAll("path")
    .data(BeijingGeoJson.features) // Data binding
    .join("path")
    .attr("d", pathGenerator) / / draw the path
    .attr("stroke-width".0.5)
    .attr("stroke"."# 000000")
    .attr("fill"."#ffffff");
Copy the code

At this point, the basic map has been drawn.

D3.js mapping _ Basics

This article is not only about mapping, but also about zooming and dragging.

Zoom and drag the map

All we need to do is add the Zoom behavior to the base version code, which looks like this

function zoomed() {
    const t = d3.event.transform;
    svg.attr("transform".`translate(${t.x}.${t.y}) scale(${t.k}) `);
}
const zoom = d3.zoom()
               .scaleExtent([1.3])  // Set the listening scope
               .on("zoom", zoomed);  // Set the listening event
    
svg.call(zoom); / / application
Copy the code

So now we can scale and pan.

However, when the zoom is 1, drag and pan will show a very strange behavior, which is jitter (this may be because the GIF frame number is low, you can download the Github code here to try: map drag – “jitter version”).

Problem solving

Why does it cause jitter? The reason is that when an element (in this case, an SVG element) listens to the event, Zoom records the mouse position of the clicked element, and when you drag it, it changes the position of the clicked element, so it shakes when you move it.

In the following GIF, we can see that the position of SVG keeps changing!

How to solve the problem is very simple, we just need to keep the position of the listening element unchanged (in this case, SVG element)

We insert a < G > tag in the original SVG, and place the map’s path path in the < G > tag. The event is still mounted on the SVG, but drag and zoom is applied to the

element, so that the position of the monitored element does not change.

const mapContainer = svg.append("g"); // Add mapContainer to load the map drawing content
 / /...
 / /...
const mapPath = mapContainer.selectAll("path")
    .data(BeijingGeoJson.features) // Data binding
    .join("path")
 / /...
 / /...
function zoomed() {
    const t = d3.event.transform;
    mapContainer.attr("transform".`translate(${t.x}.${t.y}) scale(${t.k}) `); // Change the location and scaling of mapContainer
}
/ /...
/ /...
svg.call(zoom)
Copy the code

At this point, there is no jitter problem. GitHub addresses are as follows: map drag without dithering

conclusion

This document documents the steps for learning to draw a map, which is the most basic step, but once you have mastered this step and flow it is very easy to add other actions such as click events, path path coloring, tag adding, and so on, consistent with basic D3.

If have inadequacy place, still ask big guy to instruct.

Three GitHub addresses for Demo:

  • D3.js mapping _ Basics
  • Map drag – “Dither version”
  • Map drag – no jiggling

The resources

GeoJSON – Wikipedia

Making a map using d3.js D3 官网 – d3-geo StackOverflow Center a map in D3 given a geoJSON object D3 website — the projection. FitExtent (among other, GeoPath path. Map Projection (d3) — Projection Projection (d3) — Projection Projection (d4) Cartography, Part 1 Lesson 15 Map — December Cafe

zoom

d3.behavior.zoom jitters, shakes, jumps, and bounces when dragging

understanding zoom behavior bindings

D3 force layout: making pan on drag (zoom) smoother