【问题标题】:Multiple maps with d3.js: change values of scale and center使用 d3.js 的多个地图:更改比例和中心的值
【发布时间】:2017-11-22 00:02:20
【问题描述】:

我正在构建一个 (d3 v4) 制图可视化,它允许用户在许多数据集(json 文件)和两个不同的区域(一个国家和较小的行政单位并入其首都)。实际上,通过按钮和 jquery 在初始国家/地区级别从一个数据集切换到另一个数据集效果很好。

问题:切换到关于首都城市的地图/数据集时说服力稍差,因为投影最初是为整个国家/地区设置的,因此用户必须多次缩放才能可视化正确的首都地图。我想在调用投影时更改 .scale 和 .center 的值,但经过几次尝试我还没有找到方法。

由于我只有两个不同的区域要显示,我的直觉是设置 scale 和 center 的第一个值并将它们更改为其他值(我知道 .scale 和 .center 的值我想在这两种情况下使用) 当用户通过功能切换到首都的地图时。有没有可能轻松切换这些值?你对解决这个问题有什么建议吗?

当用户单击按钮切换到另一个数据集时,当我将 json 文件路径加载到函数中时,我试图以相同的方式加载 scale 的值,但我可能做错了。好像关于投影的部分代码不能放在函数中?

感谢您的帮助!

我的代码的一小部分:

var width = 1100, height = 770;

var projection = d3.geoConicConformal()
    .scale(19000) // value I would like to which when the region changes
    .center([4.45, 50.53]) // value I would like to which when the region changes
    .translate([width/2,height/2]);

var svg = d3.select( "#mapcontainer" )
    .append( "svg" )
    .attr("width", width)
    .attr("height", height)
    .style("border", "solid 1px black");

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

var color, jsonfile, legendtext;

function load (jsonfile, legendtext, color) {
    d3.selectAll(".currentmap").remove() ;
    d3.json(jsonfile, function(error, belgique) {
        g.selectAll("path")
        .data(belgique.features)
        .enter()
        .append("path")
        .attr("d", path)
        .style("stroke", "#fff")
        .attr( "class", "currentmap")
        .style("fill", function(d) {
            var value = d.properties.DATA;
            if (value) {return color(value);}
            else {return "rgb(250,110,110)"}
            });
            })
};

//one of the following function for each map
function BGQprovinces() { 
    jsonfile = "ATLAS/NewGeoJson/bgq-data1-provinces.json";
    legendText [= …];
    color = d3.scaleOrdinal()
                .domain( […])
        .range([…]);

    load(jsonfile, legendtext, color) ; 
    };

;

【问题讨论】:

    标签: d3.js geojson map-projections


    【解决方案1】:

    实现这一点的方法很少。

    fitSize 和 fitExtent

    一种是修改投影比例和平移,而不是比例和中心。这几乎是相同的操作,但平移平移投影平面和中心将平移未投影平面。为此,您需要使用 projection.fitSize([width,height],geojsonObject) 或 projection.fitExtent([[x0,y0],[x1,y1]],geojsonObject)。后者将允许边距,例如,提供的第一个坐标是左上角,提供的第二个坐标是边界框的右下角,其中将限制特征。

    d3.json(jsonfile, function(error, belgique) {
         projection.fitSize([width,height], belgique);
    
        // now draw as you would:
        d3.selectAll(".currentmap").remove() ;
        g.selectAll("path")
        .data(belgique.features)
        .enter()
        .append("path")
        .attr("d", path)
        ...
    

    请注意,要显示一个国家/地区的所有内容,您需要有一个显示整个国家/地区的地图项或显示一个国家/地区所有部分的地图项集合。您不能将数组与 fitSize 或 fitExtent 一起使用,如果您有一组特征,则可以使用以下方法创建特征集合:

    var featureCollection = {"type":"featureCollection","features":featureArray}
    

    对于您的情况,我建议使用 fitSize 或 fitExtent。

    质心

    如果你真的想修改中心属性而不是平移,或者你想改变旋转(世界上许多地方圆锥形保形的结果更可能,比利时应该没问题),那么你需要中心的地理坐标。少数几种方法是从 path.geoCentroid 获取特征的质心:

    var centroid = path.geoCentroid(geojsonObject); 
    

    然后用它来设置投影参数旋转:

    projection.rotate([ -centroid[0],-centroid[1] ])
    projection.center([0,0])
    

    或居中:

    projection.rotate([0,0])
    projection.center(centroid)
    

    或两者的组合(取决于地图投影类型)。现在您可以应用 fitSize 或 fitExtent,该功能已经在中间,但现在我们可以设置比例。我建议将其作为潜在答案的原因是,并非所有投影,尤其是圆锥投影,都会通过仅修改比例以及平移和/或中心来获得所需的结果。

    当然,对于圆锥投影,您可能还需要找到一种方法来设置平行线,但如果它出现,我会留给另一个答案。

    【讨论】:

    • 非常感谢您的回答@AndrewReid,您解决了我的问题!我还没有尝试过第二个建议,因为 fitSize 和 fitExtent 都可以完美地工作(fitExtent 更好)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多