Display geographic data using d3 with geoJSON

I am struggling to render a geoJSON file using d3 because I am having trouble targeting the correct features for projection.

Instead of working with the typical us.json file used in many d3 examples, my current map focuses on United States "Commuting Zones" (CZ's) rather than land, states, or counties.

In my usual process, I call

topojson.feature(us, us.objects.states)

to display the correct layer. However, the file I'm currently working with is not organized into objects and does not have multiple layers. Here is an excerpt from the geoJSON file:

{"type":"FeatureCollection","bbox":[-120.30602148510043,6.667736880597216,-70.95829310710806,34.46308750538215],"features":[{"type":"Feature","geometry":{"type":"Polygon","coordinates":[[[-83.802805983004,22.64602264051764],[-83.8080569412408,22.638128812605782],

Below is the code I am using, which is not successfully rendering the map:

d3.json("CZ90.zip.geojson", function(error, us) {
    if (error) throw error;

    d3.select("svg").append("path")
        .datum(topojson.feature(us, us.CZ90))
        .attr("d", d3.geo.path());
});

Since there are no objects defined in the file, I omitted the ".object". When I view the file in Mapshaper, it renders correctly with a layer titled "CZ90", leading me to try "us.CZ90" instead of "us.objects.states"

I understand that I may be using "topojson.feature" instead of something geoJSON specific, but I have been unsuccessful in converting the file to topoJSON in Mapshaper without losing projection information.

What is the right way to target this layer in the .datum call?

This issue would be resolved if I could find a topoJSON file similar to us.json that includes a commuting zones layer!

Answer №1

After receiving assistance from a developer friend of mine, I discovered that the solution to my problem was much simpler than I had initially thought.

It turns out that d3.json() is inherently designed to interpret the structure of my geoJSON file without requiring the use of datum(). All I needed to do was make the following call:

d3.json("CZ90.zip.geojson", function(error, geoData) {
    d3.select("svg").append("path")
        .attr("d", path(geoData));
}

Just a side note: this code snippet is based on d3.v4

Below is the complete script that successfully rendered the map:

<!DOCTYPE html>
<meta charset="utf-8">
<style>
    path {
      fill: #ccc;
      stroke: #fff;
      stroke-linejoin: round;
    }
</style>

<svg width="960" height="500"></svg>
<script src="//d3js.org/d3.v4.min.js"></script>

<script>

var width = 960;
var height = 620;

var chosenProjection = d3.geoMercator()
  .scale(600)
  .translate([1300, 450])

  var path = d3.geoPath()
    .projection(chosenProjection);

d3.json("CZ90.zip.geojson", function(error, geoData) {

  d3.select("svg").append("path")
      .attr("d", path(geoData));
});

</script>

I hope this explanation can assist others who may find themselves stuck on a seemingly simple obstacle!

Answer №2

Upon reviewing the topojson documentation, it is clear that topojson.feature:

Returns the GeoJSON Feature or FeatureCollection for the specified object in the given topology. If the specified object is a GeometryCollection, a FeatureCollection is returned, and each geometry in the collection is mapped to a Feature. Otherwise, a Feature is returned.

Additionally, according to the d3 documentation, a d3 geopath:

Renders the given object, which may be any GeoJSON feature

Regarding this statement:

I realize I'm calling "topojson.feature" instead of something geoJSON specific

It should be noted that you are already using something geoJSON specific. Topojson.js is used to convert topoJSON back to geoJSON for D3 map usage. So, in response to your inquiry:

What is the correct way to target this layer in the .datum call?

The appropriate method is simply:

.datum(us) // feature collection or single feature

This will append a single path. However, if you wish to append multiple paths with the same dataset (for different coloring or mouse interaction):

.data(us.features) // feature collection

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Highcharts 3D Pie Chart with Drilldown Feature

How can I create a 3D Pie Chart with Drilldown effect? I am having trouble understanding how it works. Here is a JsFiddle Demo for a 3D Pie Chart: JsFiddle Demo And here is a JsFiddle Demo for a 2D Pie Chart with Drilldown feature: JsFiddle Demo You can ...

The error message "app.use() function requires middleware function" appears when the app

Currently, I am in the process of learning node.js with express template engine by following a Udemy course called "Learn Node.js by Building 10 Projects". During one of the lectures, when the professor ran npm start localhost:3000, it worked fine for him, ...

Utilize PowerShell to access JSON fields by name through converting a string to JSON

How can I retrieve the value of $body.uuid? Here is my attempt: $body = @" { "uuid": "Test07", "subject": "Template07-Subject", } "@ $bodyJSON = ConvertTo-Json $body Write-Host $bodyJSON Write-Host "uuid=$($bodyJSON.uuid)" Write-Host "uuid=$($body ...

Collection of various data points stored in a JSON format

Is there a way to efficiently retrieve multiple values from a JSON complex object or multidimensional array? { "Items": [{ "node": { "titre": "myTitle", "representation": { "1": "09 Octobre 2012 - 19:30" ...

Using Vue3 to set attributes on web components

I recently developed a self-contained web component using Vite and Vue3 to replace outdated jQuery libraries. When this component is rendered in HTML, it appears like this: <custom-datepicker id="deliveryTime"> #shadow-root <div> ...

tips for retrieving global variables from ajax calls using promises

Currently, I am retrieving data and storing it in global variables in a less than optimal way. Here is the current method: var tranlationJson = $.ajax({ type: "GET", url: "translation.xml", contentType: "text/xml", dataType: "xml", ...

Implementation of multiple angular guards causing a crash on the page

I have been attempting to implement separate guards for distinct pages. Essentially, I am checking a boolean parameter to determine if a user is logged in or not. Below are the two guard.ts codes that I am using: export class IsAuthenticatedGuard implemen ...

Guide to assigning IDs to multiple paragraphs within a parent element using a for loop

Is there a way to use a for loop to set ID for each <p> inside a <div> element? HTML <div id="article"> <p>1</p> <p>2</p> <p>3</p> <p>4</p> <p>5</p> ...

Using AngularJS, learn how to populate array objects within a JSON object

I'm trying to load array objects from a multi-select control, then populate a model object called "name" with its name and age values. After that, I want to load an array from a select element into the model object. However, the ng-model directive on ...

Transform your HTML audio player into a Vue component

I am in the process of converting an HTML player into a Vue component. Half of the component has been successfully converted, but the time control slider is still missing. Below is the original HTML code for the player: // JavaScript code for the audi ...

The function cannot be applied to the size of the map within the action payload

Is there a way to replace the for loop with the map method? The data structure for book.pages is in the format [{},{},{}] I tried using the size method and included this line console.log("book.pages.map.size();--->", book.pages.map.si ...

The 'name' property of Axios and Vuex is not defined and cannot be read

When making a call to axios in my mounted function to retrieve profile data, I send the payload to the 'set_account' Vuex store upon success. To access this data, I utilize MapGetters (currentAccount) in computed properties. However, when tryin ...

When utilizing the array.push method, new elements are successfully added, however, it appears to also overwrite the last object

I'm encountering a strange issue where every time I push an object to the array, the array's length increases as expected. However, the object that I push last ends up overriding all other objects. I can't seem to figure out my mistake, so p ...

Transferring information into MySQL through an Android application

I am new to developing a web application for Android and it's my first time experimenting with it. I am encountering an error where a string cannot be converted to a JSONObject. Despite trying everything, I have not been able to find a solution yet. H ...

Is there a way to capture the input from the text box and store it in the local storage?

I'm confused about why the data entered into the input box is not being saved to local storage. <body> <input id="name"> <button onclick="bob()"> save </button> </body> <script> const user = document.getElementByI ...

What could be causing the issue of the view not showing up in AngularJS?

I've been trying to use AngularJS modules to display a view, but for some reason my page isn't showing up. Can anyone help me figure out what's going on? You can check out my code at the following link: <!DOCTYPE html> <html> & ...

Securing $_FILES Filenames in PHP

I have a form with an "attachments" field where users can add multiple attachments. Before uploading each attachment, I use a function to make the file name safe. Here is the function: function safeFile($file) { $lower = strtolower($file); $trim ...

submit a new entry to add a record to the database

Hey there, I recently started learning PHP and JS and I'm trying to insert a row into a WordPress database table. I need to get the information needed for insertion from another table, but I'm facing an issue with the PHP file as it's not in ...

Ensuring Unique CSS for Diverse Devices: A User-Agent Driven Approach

I am facing multiple challenges and working towards finding solutions. I have developed a webpage and now I want to redirect the link to the CSS file based on the user agent. `<script type="text/css" src="style.css"> </script>` However, inst ...

Exploring ways to access elements within shadow-root (open) in Angular using SVG.js

I'm currently tackling a project involving Angular Elements. Within this specialized component, my goal is to incorporate SVG.js 3+. However, due to the necessity of utilizing ViewEncapsulation.ShadowDom in my component, I am encountering challenges w ...