#javascript #jquery #d3.js #data-visualization
Вопрос:
Я работаю над этим проектом, и у меня есть карта-схема. Я использую ссылку geojson для получения данных для всей карты. Что я хочу сделать, так это когда я нажимаю на любую страну, чтобы перейти по другой ссылке с идентификатором этой конкретной страны. Я должен использовать два набора данных, один для визуализации карты из файла geojson, а другой для моих фактических данных. Как я могу использовать два набора данных в одном элементе d3
Вырезанный код находится ниже этого:
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>
Обратите внимание: функция onclick работает хорошо прямо сейчас, но если я нажму, например, на Россию, это даст мне идентификатор этого файла geojson для России, который является «RUS», но на самом деле мне нужен идентификатор из моей таблицы, который равен «5» для России.
Ответ №1:
Вы можете получить название страны из набора данных, которые вы используете для своей карты, а затем найти идентификатор в myTable var.
Итак, ваше мероприятие будет
.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();
})
ИЗМЕНИТЬ: добавлен фрагмент кода, который печатает URL-адрес с идентификатором страны. Если вы нажмете на Россию, вы сможете ее увидеть 🙂
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>
Комментарии:
1. Я получаю эту ошибку: моя таблица. поиск — это не функция . Можете ли вы объяснить мне, как работает datum ? Потому что я не вижу, где он инициализируется с обоими наборами данных
2. Конечно, datum — это способ d3 для получения информации об элементах- ссылка на документы — github.com/d3/d3-selection/blob/v3.0.0/. … Вы можете просмотреть журнал консоли, чтобы просмотреть все данные, чтобы понять идею.
3. @Leo Я добавил фрагмент кода для вашей ссылки на ответ)
4. Выглядит все хорошо. Я решил поработать с этими данными geojson insead. У него тоже есть идентификатор, поэтому мне пришлось восстановить свою базу данных и заставить ее работать с данным идентификатором. Большое спасибо за ваше время и усилия. Сильно истощен.
5. @Лео, нет проблем!