Filling d3.js map with colors depending on data from json

Viewed 227

So new to d3, this is my first project using the library. Currently, I'm having issues with filling the map with different colours depending on the data. I found lots of examples on the web but they are not really working for me.

What I have is a JSON file with data in this format

"Aska": {
    "opening_bal": 138000,
    "total_funds": 1030574000,
    "expenditure_wages": 796017000,
    "expenditure_materials": 234236000,
    "total_expenditure": 1030491000,
    "unspent_bal": 78000,
    "payment_due": 12780000
  },
  "Balasore": {
    "opening_bal": 4660000,
    "total_funds": 233869000,
    "expenditure_wages": 203883000,
    "expenditure_materials": 57571000,
    "total_expenditure": 262518000,
    "unspent_bal": 28658000,
    "payment_due": 2118000
  },

I'm able to create the map using GeoJson file. Here is the link to the map: https://mgnregs-d3.vercel.app/filter

I'm thinking of creating an object using the initial category, "opening_bal" eg:

{
  "Aska": 138000,
  "Balasore": 4660000
},

and on click, I'll update the category to "total_funds" and so on, eg:

{
  "Aska": 1030574000,
  "Balasore": 233869000
},

but first I need to visualise the initialise the first data. I am not able to do that.

Something like this worked on some projects, but not on my case...

d3.json('data.json', function (d) {
    budget.d.properties.pc_name = d.properties.pc_name['opening_bal']
})

var color = d3
    .scaleThreshold()
    .domain(d3.range(2, 18))
    .range(d3.schemeBlues[6])

Here is the repo on GitHub: https://github.com/PixeledCode/MGNREGS_D3

Map Component: https://github.com/PixeledCode/MGNREGS_D3/blob/main/src/components/Filter/Filter.js

data.json: https://github.com/PixeledCode/MGNREGS_D3/blob/main/src/assets/data.json

Map GeoJson: https://github.com/PixeledCode/MGNREGS_D3/blob/main/src/assets/odihsa.js

Any help is appreciated.

1 Answers

You have a data object in the following form:

const data = {
  "Aska": 138000,
  "Balasore": 4660000,
  ...
},

Find minimum and maximum values of the object:

const range = Object.values(data).reduce((r, v) => r ? 
  ({min: Math.min(r.min, v), max: Math.max(r.max, v}) :
  ({min: v, max: v})), null);

Now, you can write a function translating any value between minimum and maximum to a color. If your color for minimum value is green (0, 255, 0), and the color for maximum value is blue (0, 0, 255), the function will look like this:

const colorUnit = 255 / (range.max - range.min);
const getColorByValue = val => {
  const delta = val - range.min;
  return `rgb(0, ${255 - delta * colorUnit}, ${delta * colorUnit})`;
};
Related