I am working on this project and I have a map chart. I am using a geojson link for getting the data for all the map. What I want to do is when I click on any country, to take me to another link, with the ID of that specific country. I have to use two datasets, one for visualizing the map from geojson file and the other one for my actual data. How can I use two datasets in one single element of d3
The Code snipped is below this:
var margin = {
top: 0,
right: 0,
bottom: 0,
left: 0
},
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
var color = d3.scaleThreshold()
.domain([10000, 100000, 500000, 1000000, 5000000, 10000000, 50000000, 100000000, 500000000, 1500000000])
.range(["rgb(247,251,255)", "rgb(222,235,247)", "rgb(198,219,239)", "rgb(158,202,225)", "rgb(107,174,214)", "rgb(66,146,198)", "rgb(33,113,181)", "rgb(8,81,156)", "rgb(8,48,107)", "rgb(3,19,43)"]);
var path = d3.geoPath();
var svg = d3.select("#map")
.append("svg")
.attr("width", width)
.attr("height", height)
.append('g')
.attr('class', 'map');
var projection = d3.geoMercator()
.scale(130)
.translate([width / 2, height / 1.5]);
var path = d3.geoPath().projection(projection);
var myTable = [{
"id": "1",
"name": "China",
"population": "1330141295"
},
{
"id": "2",
"name": "India",
"population": "1173108018"
},
{
"id": "4",
"name": "United States",
"population": "310232800"
},
{
"id": "3",
"name": "Indonesia",
"population": "242968342"
},
{
"id": "5",
"name": "Russia",
"population": "201103330"
}
];
queue()
.defer(d3.json, "https://gist.githubusercontent.com/micahstubbs/8e15870eb432a21f0bc4d3d527b2d14f/raw/a45e8709648cafbbf01c78c76dfa53e31087e713/world_countries.json")
.defer(d3.tsv, "https://gist.githubusercontent.com/micahstubbs/8e15870eb432a21f0bc4d3d527b2d14f/raw/a45e8709648cafbbf01c78c76dfa53e31087e713/world_population.tsv")
.await(ready);
function ready(error, data, population) {
var populationById = {};
population.forEach(function(d) {
populationById[d.id] = d.population;
});
data.features.forEach(function(d) {
d.population = populationById[d.id]
});
svg.append("g")
.attr("class", "countries")
.selectAll("#map")
.data(data.features)
.enter().append("path")
.attr("d", path)
.style("fill", function(d) {
return color(populationById[d.id]);
})
.style('stroke', 'white')
.style('stroke-width', 1.5)
.style("opacity", 0.8)
.on('click', function (d, i) {
var win = window.open('https://www.google.com/' d.id , '_blank');
win.focus();
})
svg.append("path")
.datum(topojson.mesh(data.features, function(a, b) {
return a.id !== b.id;
}))
// .datum(topojson.mesh(data.features, function(a, b) { return a !== b; }))
.attr("class", "names")
.attr("d", path);
}
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="https://d3js.org/queue.v1.min.js"></script>
<script src="https://d3js.org/topojson.v1.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3-tip/0.7.0/d3-tip.js"></script>
<div id="map"></div>
Notice: the onclick function works all good right now but if I click on Russia for example, it would give me the id of that geojson file for Russia which is "RUS" but actually I need the id from myTable which is "5" for Russia.
CodePudding user response:
You can get a country name from the datum of data you're using for your map, then lookup the id in myTable var.
So, your event would be
.on('click', datum => {
//Get the name of the country
console.log(datum.properties.name);
// Look up id by the name
data = myTable.find(e => e.name === datum.properties.name)
console.log(data.id) // here is your country id
var win = window.open('https://www.google.com/' data.id , '_blank');
win.focus();
})
EDIT: added a code snippet that print a URL with country id. If you click on Russia, you should be able to see it :)
var margin = {
top: 0,
right: 0,
bottom: 0,
left: 0
},
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
var color = d3.scaleThreshold()
.domain([10000, 100000, 500000, 1000000, 5000000, 10000000, 50000000, 100000000, 500000000, 1500000000])
.range(["rgb(247,251,255)", "rgb(222,235,247)", "rgb(198,219,239)", "rgb(158,202,225)", "rgb(107,174,214)", "rgb(66,146,198)", "rgb(33,113,181)", "rgb(8,81,156)", "rgb(8,48,107)", "rgb(3,19,43)"]);
var path = d3.geoPath();
var svg = d3.select("#map")
.append("svg")
.attr("width", width)
.attr("height", height)
.append('g')
.attr('class', 'map');
var projection = d3.geoMercator()
.scale(130)
.translate([width / 2, height / 1.5]);
var path = d3.geoPath().projection(projection);
var myTable = [{
"id": "1",
"name": "China",
"population": "1330141295"
},
{
"id": "2",
"name": "India",
"population": "1173108018"
},
{
"id": "4",
"name": "United States",
"population": "310232800"
},
{
"id": "3",
"name": "Indonesia",
"population": "242968342"
},
{
"id": "5",
"name": "Russia",
"population": "201103330"
}
];
queue()
.defer(d3.json, "https://gist.githubusercontent.com/micahstubbs/8e15870eb432a21f0bc4d3d527b2d14f/raw/a45e8709648cafbbf01c78c76dfa53e31087e713/world_countries.json")
.defer(d3.tsv, "https://gist.githubusercontent.com/micahstubbs/8e15870eb432a21f0bc4d3d527b2d14f/raw/a45e8709648cafbbf01c78c76dfa53e31087e713/world_population.tsv")
.await(ready);
function ready(error, data, population) {
var populationById = {};
population.forEach(function(d) {
populationById[d.id] = d.population;
});
data.features.forEach(function(d) {
d.population = populationById[d.id]
});
svg.append("g")
.attr("class", "countries")
.selectAll("#map")
.data(data.features)
.enter().append("path")
.attr("d", path)
.style("fill", function(d) {
return color(populationById[d.id]);
})
.style('stroke', 'white')
.style('stroke-width', 1.5)
.style("opacity", 0.8)
.on('click', datum => {
//Get the name of the country
console.log(datum.properties.name);
// Look up id by the name
data = myTable.find(e => e.name === datum.properties.name)
console.log('https://www.google.com/' data.id) // here is your country id
})
svg.append("path")
.datum(topojson.mesh(data.features, function(a, b) {
return a.id !== b.id;
}))
// .datum(topojson.mesh(data.features, function(a, b) { return a !== b; }))
.attr("class", "names")
.attr("d", path);
}
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="https://d3js.org/queue.v1.min.js"></script>
<script src="https://d3js.org/topojson.v1.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3-tip/0.7.0/d3-tip.js"></script>
<div id="map"></div>