Utilize D3.js to display topoJSON data on your website

My project involves creating a visualization of the India map using d3 and GeoJSON. However, I am facing difficulties in properly displaying each Indian state on the map. Any assistance in identifying and resolving the issue would be greatly appreciated. Thank you in advance.

Below is the source code that I have been working with, utilizing data from . My objective is to utilize D3.js for rendering the Indian states.

<html>

<head>
  <meta charset="utf-8">
  <title>A D3 map using topojson</title>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/queue-async/1.0.7/queue.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/topojson/1.6.19/topojson.min.js"></script>

  <link href="http://fonts.googleapis.com/css?family=Montserrat" rel="stylesheet" type="text/css">
  <style>
    path {
      fill: #ccc;
      stroke: #fff;
      stroke-width: .5px;
    }
    
    path:hover {
      fill: red;
    }
  </style>
</head>

<body>
  <script>
    var width = 900,
      height = 600;

    var path = d3.geo.path();

    var svg = d3.select("body").append("svg")
      .attr("width", width)
      .attr("height", height);

    queue()
      .defer(d3.json, "https://www.covid19india.org/mini_maps/india.json")
      .await(ready);

    function ready(error, counties) {
    svg.append("g")
    .selectAll("path")
    .data(topojson.feature(counties, counties.objects.ele).features)
    .enter()
    .append("path")
    .attr("d", path)
    .attr("class", "state");
    }
  </script>
</body>

</html>

The current output I am receiving is not as expected. Can anyone provide guidance on identifying the issue? As a student, I am still learning about this process.

Answer №1

To utilize the already projected JSON, simply input null into the projection function:

var path = d3.geo.path()
    .projection(null);

Your updated code will look like this:

<html>

<head>
  <meta charset="utf-8">
  <title>A D3 map using topojson</title>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/queue-async/1.0.7/queue.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/topojson/1.6.19/topojson.min.js"></script>

  <link href="http://fonts.googleapis.com/css?family=Montserrat" rel="stylesheet" type="text/css">
  <style>
    path {
      fill: #ccc;
      stroke: #fff;
      stroke-width: .5px;
    }
    
    path:hover {
      fill: red;
    }
  </style>
</head>

<body>
  <script>
    var width = 900,
      height = 600;

    var path = d3.geo.path()
      .projection(null);

    var svg = d3.select("body").append("svg")
      .attr("width", width)
      .attr("height", height);

    queue()
      .defer(d3.json, "https://www.covid19india.org/mini_maps/india.json")
      .await(ready);

    function ready(error, counties) {

      svg.append("g")
        .selectAll("path")
        .data(topojson.feature(counties, counties.objects.states).features)
        .enter()
        .append("path")
        .attr("d", path)
        .attr("class", "state");
    }
  </script>
</body>

</html>

Answer №2

Check out the response provided by @Gerardo above which pertains to D3 version 3.

For those seeking a solution for D3 version 6, see below:

Note: The method d3.geo.path() has been updated to d3.geoPath() in D3 version 6.

// Specifics: https://stackoverflow.com/a/66622694/6908282

var width = 900,
      height = 600;

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

    var svg = d3.select("body").append("svg")
      .attr("width", width)
      .attr("height", height);

 fetch("https://www.covid19india.org/mini_maps/india.json")
            .then(response => response.json())
            .then(json => {
                svg.append("g")
                    .selectAll("path")
                    .data(topojson.feature(json, json.objects.states).features)
                    .enter()
                    .append("path")
                    .attr("d", path)
                    .attr("class", "state");
            });
path {
      fill: #ccc;
      stroke: #fff;
      stroke-width: .5px;
    }
    
    path:hover {
      fill: red;
    }
<script src="https://d3js.org/d3.v6.min.js"></script>
<script src="https://unpkg.com/topojson@3"></script>

Answer №3

Back in the day, I managed a website named covid19news.org that is no longer active. During my time there, I worked on something quite similar to what you see below.

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <style>
    #map    { position: relative; min-height: 500px;  
       width: 800px;
    height: 770px;
    background-color: white;
}

.district, .disputed, .state rect, .state path { stroke: #a9a9a9; stroke-width: 1px; }

.district:hover { stroke: #777777; stroke-width: 1px; fill-opacity: .7; }
.state:hover rect { stroke: #777777; stroke-width: 2px; fill-opacity: .7; }
.state:hover path { fill-opacity: .7; }

#select {
    position:absolute;
    left: 500px;
    top: 100px;
        font: 12px sans-serif;
        color: #333;
}

#tooltip h3 {
        margin:2px;
        font-size:14px;
}
#tooltip h4 {
        margin:2px;
        font-size:10px;
}
#tooltip {
        position: absolute;           
        background:rgba(0,0,0,0.8);
        text-align: left;
        border:1px;
        border-radius:5px;
        font: 12px sans-serif;        
        width:auto;
        padding:4px;
        color:white;
        opacity:0;
        pointer-events: none;         
}
#tooltip table{
        table-layout:fixed;
}
#tooltip tr td{
        padding:2px;
        margin:0;
}
</style>
</head>
<body>
        <div id="map">
        </div>
    <script src="./topo/d3.v3.min.js" charset="utf-8"></script>
    <script src="./topo/d3-queue.v3.min.js"></script>
    <script src="./topo/topojson.v1.min.js"></script>
    <script>
    function districtMap(districts, disputed) {

var width  = 800, height = 700, scale = 1200;
var propTag = 'zone', ttName = 'Zone', unit = '';
var extraTop = 0, extraLeft = 0;
function render(selection) {
  selection.each(function() {

    d3.select(this).select("svg").remove();
    var svg = d3.select(this).append("svg")
                .attr("width", width)
                .attr("height", height);

    d3.select(this).select("#tooltip").remove();
    d3.select(this).append("div").attr("id", "tooltip").style("opacity", 1);

    var projection = d3.geo.mercator()
        .center([83, 23])
        .scale(scale)
        .translate([width / 2, height / 2]);

    var path = d3.geo.path().projection(projection);

    svg.selectAll(".district")
        .data(districts.features)
      .enter().append("path")
        .attr("class", "district")
        .style("fill", function(d) { return 'd.properties.zone.toLowerCase();' })
        .attr("d", path)
      .on("mouseover", function(d) {      
             d3.select("#tooltip").transition()        
                .duration(200)      
                .style("opacity", .9);     
             d3.select("#tooltip").html("<h3>"+(d.id)+"</h3><h4>("+(d.properties.NAME_1)+")</h4><table>"+
                      "<tr><td>"+ttName+"::</td><td>"+(d.properties[propTag])+"</td></tr>"+
                      "</table>")
                .style("left", (d3.event.pageX-document.getElementById('map').offsetLeft - extraLeft) + "px") 
                .style("top", (d3.event.pageY-document.getElementById('map').offsetTop - 160 - extraTop) + "px");
      })  
      .on("mouseout", function(d) {       
             d3.select("#tooltip").transition()        
                .duration(500)      
                .style("opacity", 1);   
      });
      
    svg.selectAll(".disputed")
        .data(disputed.features)
      .enter().append("path")
        .attr("class", "disputed")
        .style("fill", function(d) { return d.color; })
        .attr("d", path);

  });
} // render
render.height = function(value) {
            if (!arguments.length) return height;
            height = value;
            return render;
        };
render.width = function(value) {
            if (!arguments.length) return width;
            width = value;
            return render;
        };
render.scale = function(value) {
            if (!arguments.length) return scale;
            scale = value;
            return render;
        };
render.propTag = function(value) {
            if (!arguments.length) return propTag;
            propTag = value;
            return render;
        };
render.ttName = function(value) {
            if (!arguments.length) return ttName;
            ttName = value;
            return render;
        };
render.unit = function(value) {
            if (!arguments.length) return unit;
            unit = value;
            return render;
        };

return render;
} // districtMap
    (function() {
    d3.queue()
        .defer(d3.json, "./topo/zone-data.json")
        .defer(d3.json, "./topo/Kashmir.json")
        .await(function(error, topoMain, topoKashmir) {
            var districts, disputed;
            if (error) throw error;
            districts   = topojson.feature(topoMain, topoMain.objects.IND_adm2);
            disputed    = topojson.feature(topoKashmir, topoKashmir.objects.ne_10m_admin_0_Kashmir_Occupied);
            colorDisputed(disputed.features);

            // Map render
            var map     = districtMap(districts, disputed).width(800).height(700).scale(1200); //.propTag(filter);
          
            d3.select("#map").call(map);
       
        });
}());
          

function colorDisputed(data) {
    var color         = "#eaeafa";
    data.forEach(function(d) { 
        d.color       = color;
    });
}
    </script>
</body>
</html>

If you want to explore the full functioning code, check it out here: stackblitz

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

What are the steps to changing the navbar's color when scrolling down?

I am having trouble changing the color of my navigation bar from transparent to black after the user scrolls down. Despite trying various methods and watching tutorials, I can't seem to get it to work. HTML <nav role='navigation' class= ...

The OrhographicCamera is having difficulties capturing the entire scene in its render

Recently, I have been working on rendering a scene using three.js and WebGL in an isomorphic manner. In my research, I came across suggestions to use the OrthographicCamera for this purpose. However, upon implementing it, I noticed some strange outcomes. A ...

Steps for presenting a JSON file in a TextView

I've recently started learning about Android development and I'm struggling to grasp the concept of JSON. I have a JSON file with my data stored, but I don't know how to retrieve and display that information in my Android application. Any h ...

Using Angular to create HTTP routes in conjunction with Node.js

My current challenge involves trying to access a .json file that contains my portfolio. I have set up my backend using express js, and am attempting to retrieve the data using angular in the following manner: $http.get("data/items.json") .success(function ...

Display event using Angular

I am currently working on an Angular project where I need to print a specific area of the page. While I know that this can be done using media CSS, it is causing issues for me due to the numerous print functionalities present in the project. I am attemptin ...

developing toggle switches using JSON

I am faced with a JSON containing two keys, "cars" and "others". How can I implement a toggling feature on my website using HTML/CSS/JavaScript such that: Clicking on "cars" displays the car items (small vehicle, large vehicle) in red text. Clicking on "o ...

Iterate through the elements of a JSON array structure

I'm a beginner when it comes to Vb.net. I've encountered a JSON string below, and I attempted to deserialize it into an Object using JsonConvert.DeserializeObject(). My goal is to iterate through the values within the Content object in the JSON ...

Switch between divs using an update panel

Consider this scenario: Numerous div controls are present on an aspx page, and update panels are being used to prevent page refresh. These divs contain various controls like buttons and textboxes: <asp:UpdatePanel ID="UpdatePanel1" runat="server"> ...

Using the POST method allows for sending a distinct string from REACT to an API

I am experiencing an issue with my SQL query component. Whenever I send a query to the API-server, the backend crashes because MySQL interprets an empty string as my request. Interestingly, my backend works perfectly fine when tested using postman.exe. T ...

store array data in a JSON file without using a key

In order to create a JSON file that follows a specific format, the contents should look like this: xyz.json [ { "imagelist": "/oracle/public/oel6", "label": "test_higgs", "shape": "small", "name" : "/Compute-computecli ...

The continuous loop is triggered when attempting to pass array data from the API

Hello, I have been searching for a solution to my current issue without much success. The problem revolves around retrieving dates from Firebase and populating them into UI elements in my Vue app. My end goal is to align each date with the corresponding mo ...

Making certain parts of a select list text bold while keeping others in normal font in React

I need to create a select list that displays various products with their names and a count in bold. Here's my approach: To achieve this, I am populating an array called productInformation with each product name and its corresponding count like this: ...

Filter Angular.js by precise values (exact match)

Check out this HTML code snippet: <ul ng-repeat="friend in friends | filter: { age: '2' } | orderBy: 'name' "> <li>{{friend.name}}</li> </ul> Here is the $scope variable being used: $scope.friends = [ ...

E/AndroidRuntime: CRITICAL ERROR: main --- java code in an android app

I've been working on a map application and I've run into some issues. Can anyone help me figure out what's wrong with my code? ERROR 10-25 01:37:41.296 28673-28673/com.onemap.activities E/AndroidRuntime: FATAL EXCEPTION: main 10-25 01:37:4 ...

Send an array using jQuery's $.post method

I am experiencing an issue with sending an array in $.post to PHP. When I use var_dump, the result is showing as "NULL" and JSON.stringify is not working. JQUERY var photobox = []; photobox.push(e.target.result); $.post("../modules/upload.php",{"imag ...

Tips for dynamically rendering a React component from an object

Looking to include an imported component with some props in my React code. Unable to find a solution on Stack Overflow for this specific format. Can someone provide guidance on how to achieve this? Thanks in advance. import { HomeIcon } from "../lib/i ...

Add elements to an array with express, Node.js, and MongoDB

I'm currently learning about the MERN stack and I'm working on creating users with empty queues to store telephone numbers in E.164 format. My goal is to add and remove these numbers from the queue (type: Array) based on API requests. However, I ...

Show JSON response using AJAX jQuery

After receiving the JSON Response, { "user_data": { "id": 22, "first_name": xxx, "last_name": xxx, "phone_number": "123456789", }, "question_with_answers" : [ { "id": 1, ...

Substitute a piece of text within an element while also preserving the formatting of a new line

My goal is to modify the text within the div tag "a/b" to "b/c" while preserving the line break that I have inserted in the HTML using the break tag. Currently, the text is being replaced, but I need the second line to appear below the first line. $(".t ...

Discovering ways to determine if multiple strings are present within a single string using JavaScript

After writing this function, I noticed it only worked with a single string value. contains(input, words) { let input1 = input.split(' '); for (var i = 0; i < input1.length; i++) { if (input1[i] === words) { ...