Quantcast
Channel: Marc Neuwirth's Blog » Marc
Viewing all articles
Browse latest Browse all 10

Creating the Earth with D3.js

$
0
0

There is no way around it, creating data visualizations with D3 is just plain fun. Lately, I have especially enjoyed building map visualizations, but I hadn’t figured out an excuse to use the azimuthal projection on a project.

I still haven’t, but this Earth is pretty cool looking:

Click and drag to pan, use scroll wheel to zoom Fullscreen

There are really three parts working here:

  1. The actual map, which is an orthographic azimuthal projection of the countries of the world onto the outside of a sphere.
  2. The stars and outer space, which is a equidistant azimuthal projection onto the inside of a larger sphere
  3. A giant circle with the same diameter as the map sphere for background gradient and a Gaussian blur (SVG Filter)

Map

The map itself is pretty simple, each country is a GeoJSON ‘feature’ polygon which is just a list of lat/lon points that form the borders of the country:

{
  "type":"Feature",
  "properties":{
    "name":"Cyprus"
  },
  "geometry":{
    "type":"Polygon",
    "coordinates":[
      [
        [33.973617,35.058506],
        [34.004881,34.978098],
        [32.979827,34.571869],
        [32.490296,34.701655],
        [32.256667,35.103232],
        [32.73178,35.140026],
        [32.919572,35.087833],
        [33.190977,35.173125],
        [33.383833,35.162712],
        [33.455922,35.101424],
        [33.475817,35.000345],
        [33.525685,35.038688],
        [33.675392,35.017863],
        [33.86644,35.093595],
        [33.973617,35.058506]
      ]
    ]
  },
  "id":"CYP"
}

Each country is mapped to a spot on the page according to the projection, and the paths are clipped so that only the ones on the visible side of the sphere are shown.

Stars

Outer space is the inside of a sphere that is three times the size of the Earth itself. It is also another map projection, but instead of countries, there are 300 randomly placed points of varying sizes. These points are supposed to look like stars and create the backdrop for the Earth.

Polish

In order to make this look more like the Earth, there is a single SVG circle element behind all of the map data. The circle uses a SVG linearGradient and filter for a little bit of a 3D spherical look and the fuzzily defined edge caused by the atmosphere.

<svg id="defs">
    <defs>
        <linearGradient id="gradBlue" x1="0%" y1="0%" x2="100%" y2="0%">
            <stop offset="0%" style="stop-color:#005C99;stop-opacity:1" />
            <stop offset="100%" style="stop-color:#0099FF;stop-opacity:1" />
        </linearGradient>
        <filter id="glow">
            <feColorMatrix type="matrix"
                values=
                "0 0 0 0   0
                 0 0 0 0.9 0
                 0 0 0 0.9 0
                 0 0 0 1   0"/>
            <feGaussianBlur stdDeviation="5.5" result="coloredBlur"/>
            <feMerge>
                <feMergeNode in="coloredBlur"/>
                <feMergeNode in="SourceGraphic"/>
            </feMerge>
        </filter>
    </defs>
</svg>

Moving Around

D3 makes panning and zooming pretty easy to figure out with maps, however it is mostly tuned for the more often used projections like Albers and Mercator, which use the translate property instead of the origin to control the focal point. That works great for those projections because it allows the scrollwheel to zoom in on the mouse pointer as it does in Google Maps.

Unfortunately, that paradigm doesn’t work as well for this azimuthal projection, so we need to detach the pan and zoom events from affecting each other. This isn’t currently an option in D3, so I have a pull request with a fix that will hopefully be merged soon. Until then, I am using a custom version with my change already merged.

Now that panning and zooming are separated, the move function will calculate the origin and scale based on the mouse event and change the projections for the map and outer space accordingly. Then, the map will be redrawn using the new projections. This creates a smooth experience that allows your to pan and zoom around the Earth.

Feel free to play with the demo above and look through the code below or fork it on GitHub.


Viewing all articles
Browse latest Browse all 10

Latest Images

Trending Articles



Latest Images