双击欧洲数据可视化
Double clicking Europe data visualization
我想创建一个可以缩放的欧洲等值线图。
我还想看到当用户双击一个国家时,这个国家被放大并分成多个区域(NUTS 2),每个区域根据第二个度量着色。
举个例子:
假设欧洲由5个国家组成:Country1, ..., Country5。
每个国家根据第一个指标(假设居民人数)着色。
当用户双击 Country4 时,地图会缩放,这样 Country4 就会位于屏幕的中央并可以完整查看。相邻国家可能被裁剪和模糊。
Country4 现在显示为由其区域(R1、...、R6)组成。这些地区根据第二个衡量标准(假设人均收入)着色。
在第二种情况下,我希望未选择的国家(因此国家 1、2、3 和 5)仍根据措施 1 着色。
所以我想要一些东西 like this 但可以双击并更详细地查看每个国家/地区。
我怎样才能做这样的事情?
我还没有找到对我有用的示例。
我发现 these json files and this one 我认为它们很有用(但我不知道如何使用它们)。
谢谢
我发现 this file representing the nuts2 (regions) and this 代表 nuts0(国家/地区)。
如何合并两者?思路是从nuts2.json
开始,加上nuts0.json
的信息,但是geometries
和arcs
怎么办呢?我不想造成不一致..
这是一个非常广泛的问题,包含几个问题和目标(地图缩放、等值线创建、两层地图),因此,任何答案都将是广泛的——但不一定没有帮助。我的回答不会解决问题中的所有问题,但应该有助于创建您预期的最终愿景。我将重点关注看似关键的问题:
I would also like to see that when the user double-clicks on a
country, the country in question is zoomed and divided into regions,
each of which is colored according to a second measure.
虽然你说"also"这表明这是次要的,但你的图片和标题似乎更关心两层效应,并且有很多等值线的例子和问题,但在交互式两层地图上很少。
我认为关键的挑战是细分区域,为此您需要在 parent 和 child 区域之间使用某种通用标识符。如果需要,您可以在您的 geojson 或 topojson 中添加必要的标识符。理想情况下,您的 geojson 可能如下所示:
Parent/Country:
{
"type":"Feature",
"properties"{ "country":NAME ... },
"geometry": { ... }
}
Child/Region:
{
"type":"Feature",
"properties"{ "country":NAME, "regionName": NAME ... },
"geometry": { ... }
}
当点击一个国家(或任何其他事件,如双击)时,您想根据共享标识符绘制 children 区域:
country.on("click", function(d) {
// remove other regions
d3.selectAll(".region").remove();
// filter out relevant regions of a geojson of all regions
var countryRegions = geojson.features.filter(function(region) {
return region.properties.country == d.properties.country;
})
// append the regions
svg.selectAll(".region")
.data(countryRegions)
.enter()
.append()
.attr("class",".region")
})
如果您有标准化命名的 geojson 文件,您可以使用文件名作为共享 属性,按照以下方式做一些事情:
country.on("click", function(d) {
// remove other regions
d3.selectAll(".region").remove();
// get appropriate geojson:
d3.json(d.properties.country+".json", function(error, regions) {
// draw region features
})
})
您可以通过在 click/other 事件中添加诸如 country.style("opacity",0.4)
之类的内容来提高 click/other 事件中国家/地区的透明度,模糊会增加一些复杂性。两者都应该增强两层效应。在处理国家时不需要裁剪 - 国家很少重叠,并且在任何情况下,新特征通常绘制在旧特征之上(这消除了由于坐标不精确导致的任何视觉重叠)。
这就是两层效果的全部内容,使用相同的原理,您可以轻松创建三层地图,用子区域填充选定区域。
在此基础上,我将简要介绍一下缩放:
使用包含该区域的 geojson/topojson,然后您可以更改投影以反映要素的范围 - 这样您就可以缩放到这些要素:
projection.fitSize([width,height],geojsonObject);
请注意,如果过滤特征数组,fitSize of fitExtent 将不起作用,除非您将特征放在特征中 collection(两者都需要 v4):
var featureCollection = {type:"FeatureCollection",features:features};
要实现平滑缩放,您需要使用 transition.attrTween 转换投影。这有点棘手,因为您需要对投影平移和投影比例进行插值(并且取决于地图投影和类型,可能还有旋转)。
或者,您可以通过操纵 svg 来缩放,有很多关于如何实现这种效果的示例和问题(我在下面的示例中使用了其他方法)。
以上将让您:缩放到区域、绘制相关区域以及在 regions/views.
之间转换
我制作了一个简单的通用示例,使用虚拟地理数据,即 operational here,(使用单击事件),关键部分在下面有更多注释(除了转换功能,请参阅示例以查看它)。此示例需要大量调整才能匹配您的预期数据和可视化效果。
我使用了一些未在下面的代码中声明的变量(请参阅 example 了解完整代码),但它们大多是标准的:geoPath (path
)、geoProjection (projection
)、宽度、高度等,还有 baseProjection
,这是起始投影。我也在使用虚拟数据,因此我使用 d3.geoIdentity
而不是更标准的投影 .
// get the parent geojson
d3.json("geojson.json", function(error, geojson) {
if (error) throw error;
// get the regions:
d3.json("geojsonSubdivisions.json", function(error, subdivisions) {
if (error) throw error;
// a color scale for the countries:
var color = d3.scaleLinear().range(["steelblue","darkblue"]).domain([0,4]);
// a color scale for the regions:
var subdivisionColor = ["lightsalmon","salmon","coral"];
// refine the two projections, one for the default/base, and one for the current
baseProjection.fitSize([width,height],geojson);
projection.fitSize([width,height],geojson);
// append the countries:
svg.append("g")
.attr("class", "topLevel")
.selectAll("path")
.data(geojson.features)
.enter()
.append("path")
.attr("fill",function(d,i) { return color(i); })
.attr("opacity",0.7)
.attr("d", path)
.style("stroke","black")
.style("stroke-width",0)
// style on mouseover:
.on("mouseover", function() {
d3.select(this)
.style("stroke-width",15)
.raise();
})
// undo mouseover styles:
.on("mouseout", function(d,i) {
d3.select(this)
.style("stroke-width", 0 );
})
// now zoom in when clicked and show subdivisions:
.on("click", function(d) {
// remove all other subdivisions:
d3.selectAll(".subdivision")
.remove();
// get new features:
var features = subdivisions.features.filter(function(feature) { return feature.id == d.id });
// draw new features
svg.selectAll(null)
.data(features)
.enter()
.append("path")
.attr("class","subdivision")
.attr("fill", function(d,i) { return subdivisionColor[i] })
.attr("d", path)
.style("stroke","black")
.style("stroke-width",0)
.on("click", function() {
zoom(projection,baseProjection); // zoom out when clicked
d3.selectAll(".subdivision")
.remove(); // remove regions when clicked
})
// style on mouseover
.on("mouseover", function() {
d3.select(this)
.style("stroke-width",5)
.raise(); // raise it so stroke is not under anything
})
// undo style changes on mouseout
.on("mouseout", function(d,i) {
d3.select(this)
.style("stroke-width", 0 );
})
.raise()
// make a feature collection of the regions:
var featureCollection = { "type":"FeatureCollection", "features": features }
// zoom to the selected area:
// if current projection is default projection:
if ( projection.translate().toString() === baseProjection.translate().toString() && projection.scale() === baseProjection.scale() ) {
zoom(baseProjection,projection.fitExtent([[50,50],[width-50,height-50]],featureCollection));
}
// current projection != default, zoom out and then in:
else {
// provide an end projection point for the transition:
var endProjection = d3.geoIdentity()
.reflectY(true)
.fitExtent([[50,50],[width-50,height-50]],featureCollection)
zoom(projection,endProjection,baseProjection);
}
});
});
});
我想创建一个可以缩放的欧洲等值线图。 我还想看到当用户双击一个国家时,这个国家被放大并分成多个区域(NUTS 2),每个区域根据第二个度量着色。
举个例子:
假设欧洲由5个国家组成:Country1, ..., Country5。 每个国家根据第一个指标(假设居民人数)着色。 当用户双击 Country4 时,地图会缩放,这样 Country4 就会位于屏幕的中央并可以完整查看。相邻国家可能被裁剪和模糊。
Country4 现在显示为由其区域(R1、...、R6)组成。这些地区根据第二个衡量标准(假设人均收入)着色。 在第二种情况下,我希望未选择的国家(因此国家 1、2、3 和 5)仍根据措施 1 着色。
所以我想要一些东西 like this 但可以双击并更详细地查看每个国家/地区。
我怎样才能做这样的事情? 我还没有找到对我有用的示例。
我发现 these json files and this one 我认为它们很有用(但我不知道如何使用它们)。
谢谢
我发现 this file representing the nuts2 (regions) and this 代表 nuts0(国家/地区)。
如何合并两者?思路是从nuts2.json
开始,加上nuts0.json
的信息,但是geometries
和arcs
怎么办呢?我不想造成不一致..
这是一个非常广泛的问题,包含几个问题和目标(地图缩放、等值线创建、两层地图),因此,任何答案都将是广泛的——但不一定没有帮助。我的回答不会解决问题中的所有问题,但应该有助于创建您预期的最终愿景。我将重点关注看似关键的问题:
I would also like to see that when the user double-clicks on a country, the country in question is zoomed and divided into regions, each of which is colored according to a second measure.
虽然你说"also"这表明这是次要的,但你的图片和标题似乎更关心两层效应,并且有很多等值线的例子和问题,但在交互式两层地图上很少。
我认为关键的挑战是细分区域,为此您需要在 parent 和 child 区域之间使用某种通用标识符。如果需要,您可以在您的 geojson 或 topojson 中添加必要的标识符。理想情况下,您的 geojson 可能如下所示:
Parent/Country:
{
"type":"Feature",
"properties"{ "country":NAME ... },
"geometry": { ... }
}
Child/Region:
{
"type":"Feature",
"properties"{ "country":NAME, "regionName": NAME ... },
"geometry": { ... }
}
当点击一个国家(或任何其他事件,如双击)时,您想根据共享标识符绘制 children 区域:
country.on("click", function(d) {
// remove other regions
d3.selectAll(".region").remove();
// filter out relevant regions of a geojson of all regions
var countryRegions = geojson.features.filter(function(region) {
return region.properties.country == d.properties.country;
})
// append the regions
svg.selectAll(".region")
.data(countryRegions)
.enter()
.append()
.attr("class",".region")
})
如果您有标准化命名的 geojson 文件,您可以使用文件名作为共享 属性,按照以下方式做一些事情:
country.on("click", function(d) {
// remove other regions
d3.selectAll(".region").remove();
// get appropriate geojson:
d3.json(d.properties.country+".json", function(error, regions) {
// draw region features
})
})
您可以通过在 click/other 事件中添加诸如 country.style("opacity",0.4)
之类的内容来提高 click/other 事件中国家/地区的透明度,模糊会增加一些复杂性。两者都应该增强两层效应。在处理国家时不需要裁剪 - 国家很少重叠,并且在任何情况下,新特征通常绘制在旧特征之上(这消除了由于坐标不精确导致的任何视觉重叠)。
这就是两层效果的全部内容,使用相同的原理,您可以轻松创建三层地图,用子区域填充选定区域。
在此基础上,我将简要介绍一下缩放:
使用包含该区域的 geojson/topojson,然后您可以更改投影以反映要素的范围 - 这样您就可以缩放到这些要素:
projection.fitSize([width,height],geojsonObject);
请注意,如果过滤特征数组,fitSize of fitExtent 将不起作用,除非您将特征放在特征中 collection(两者都需要 v4):
var featureCollection = {type:"FeatureCollection",features:features};
要实现平滑缩放,您需要使用 transition.attrTween 转换投影。这有点棘手,因为您需要对投影平移和投影比例进行插值(并且取决于地图投影和类型,可能还有旋转)。
或者,您可以通过操纵 svg 来缩放,有很多关于如何实现这种效果的示例和问题(我在下面的示例中使用了其他方法)。
以上将让您:缩放到区域、绘制相关区域以及在 regions/views.
之间转换我制作了一个简单的通用示例,使用虚拟地理数据,即 operational here,(使用单击事件),关键部分在下面有更多注释(除了转换功能,请参阅示例以查看它)。此示例需要大量调整才能匹配您的预期数据和可视化效果。
我使用了一些未在下面的代码中声明的变量(请参阅 example 了解完整代码),但它们大多是标准的:geoPath (path
)、geoProjection (projection
)、宽度、高度等,还有 baseProjection
,这是起始投影。我也在使用虚拟数据,因此我使用 d3.geoIdentity
而不是更标准的投影 .
// get the parent geojson
d3.json("geojson.json", function(error, geojson) {
if (error) throw error;
// get the regions:
d3.json("geojsonSubdivisions.json", function(error, subdivisions) {
if (error) throw error;
// a color scale for the countries:
var color = d3.scaleLinear().range(["steelblue","darkblue"]).domain([0,4]);
// a color scale for the regions:
var subdivisionColor = ["lightsalmon","salmon","coral"];
// refine the two projections, one for the default/base, and one for the current
baseProjection.fitSize([width,height],geojson);
projection.fitSize([width,height],geojson);
// append the countries:
svg.append("g")
.attr("class", "topLevel")
.selectAll("path")
.data(geojson.features)
.enter()
.append("path")
.attr("fill",function(d,i) { return color(i); })
.attr("opacity",0.7)
.attr("d", path)
.style("stroke","black")
.style("stroke-width",0)
// style on mouseover:
.on("mouseover", function() {
d3.select(this)
.style("stroke-width",15)
.raise();
})
// undo mouseover styles:
.on("mouseout", function(d,i) {
d3.select(this)
.style("stroke-width", 0 );
})
// now zoom in when clicked and show subdivisions:
.on("click", function(d) {
// remove all other subdivisions:
d3.selectAll(".subdivision")
.remove();
// get new features:
var features = subdivisions.features.filter(function(feature) { return feature.id == d.id });
// draw new features
svg.selectAll(null)
.data(features)
.enter()
.append("path")
.attr("class","subdivision")
.attr("fill", function(d,i) { return subdivisionColor[i] })
.attr("d", path)
.style("stroke","black")
.style("stroke-width",0)
.on("click", function() {
zoom(projection,baseProjection); // zoom out when clicked
d3.selectAll(".subdivision")
.remove(); // remove regions when clicked
})
// style on mouseover
.on("mouseover", function() {
d3.select(this)
.style("stroke-width",5)
.raise(); // raise it so stroke is not under anything
})
// undo style changes on mouseout
.on("mouseout", function(d,i) {
d3.select(this)
.style("stroke-width", 0 );
})
.raise()
// make a feature collection of the regions:
var featureCollection = { "type":"FeatureCollection", "features": features }
// zoom to the selected area:
// if current projection is default projection:
if ( projection.translate().toString() === baseProjection.translate().toString() && projection.scale() === baseProjection.scale() ) {
zoom(baseProjection,projection.fitExtent([[50,50],[width-50,height-50]],featureCollection));
}
// current projection != default, zoom out and then in:
else {
// provide an end projection point for the transition:
var endProjection = d3.geoIdentity()
.reflectY(true)
.fitExtent([[50,50],[width-50,height-50]],featureCollection)
zoom(projection,endProjection,baseProjection);
}
});
});
});