gpt4 book ai didi

javascript - D3.js:为具有多个 geoJSON 文件的 map 设置 fitExtent 或 fitSize(或以编程方式居中和缩放)

转载 作者:行者123 更新时间:2023-12-05 00:38:32 25 4
gpt4 key购买 nike

我想绘制数据来自各个 topoJSON 文件的多个国家/地区。包含这些国家的 map 应位于屏幕中间(居中),并且应设置适当的比例以使 map 填满整个窗口。

我已经尝试过的:

  • 使用 path.bounds(d) 获取边界框对于每个国家和每边(上、左、下、右)分别使用最大值和最小值,并提供来自 path.centroid(d) 的平均中心至projection.center() .这没有用。
  • 申请projection.fitExtent([[x0,y0],[x1,y1]],geojsonObject)projection.fitSize([width,height],geojsonObject)正如 this 中的建议解决方案。在这里,我无法按照描述创建 featureCollection 并使用它来创建 map 。
  • <!DOCTYPE html>
    <html lang="en">
    <head>
    <meta charset="utf-8">
    <title></title>
    <script src="https://d3js.org/d3.v5.min.js"></script>
    <script src="https://d3js.org/topojson.v2.min.js"></script>
    <style type="text/css">

    .svg-container {
    display: inline-block;
    position: relative;
    width: 100%;
    padding-bottom: 100%;
    vertical-align: top;
    overflow: hidden;
    }
    .svg-content {
    display: inline-block;
    position: absolute;
    margin: 0;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    }

    </style>
    </head>
    <body>
    <div id="container" class="svg-container"> </div>

    <script type="text/javascript">
    var width = 600; //for simplicity set to fixed value
    var height = 600; //for simplicity set to fixed value

    var projection = d3.geoMercator();

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

    var svg = d3.select("#container").append("svg")
    .classed("svg-content", true)
    .attr("width", width)
    .attr("height", height);

    //Example data
    var countries = ['germany', 'italy', 'switzerland', 'france'];

    function loadJsonFiles() {

    var files = ["https://api.myjson.com/bins/1b0ddz",
    "https://api.myjson.com/bins/11jkvb",
    "https://api.myjson.com/bins/96x1j",
    "https://api.myjson.com/bins/sspzr"];

    var promises = [];
    var allCountryData = [];

    files.forEach(function(url) {
    promises.push(d3.json(url))
    });

    return Promise.all(promises)
    .then(function(countryData) {

    for (var i = 0; i < countryData.length; i++) {

    allCountryData.push(countryData[i]);

    }
    return allCountryData;
    });
    }

    loadJsonFiles().then(function(allCountryData) {

    var allBounds = [];
    var objName;
    var countryData;

    for (var i = 0; i < allCountryData.length; i++) {

    objName = allCountryData[i].objects[countries[i]];
    countryData = topojson.feature(allCountryData[i], objName);

    //How can I use the right projection parameters for all country data loaded from topojson (outside the loop)?
    projection
    .scale(1000) //How to set this programmatically?
    .center([8,47]) //How to set this programmatically?
    .translate([width / 2, height / 2]);
    //How can I append all the country data to the svg (outside the loop)?
    svg.append("path")
    .datum(countryData)
    .attr("d", path);
    }

    });

    </script>
    </body>
    </html>

    我认为应该可以通过 Andrew Reid 在 this 中提供的建议来解决这个问题。与 fitSize 一起发布或 fitExtent .但是我无法将其应用于我的问题。这也是我解决问题的首选方式。

    或者,是否可以使用 center() 解决此问题?和 scale() ?
    我将如何确定必须向 center() 提供哪些坐标?和 scale() 的值.?
    非常感谢您的帮助,我尝试了几天但没有成功。

    最佳答案

    projection.fitSizeprojection.fitExtent两者都采用单个 geojson 对象,而不是 geojson 对象数组。幸运的是,geojson 有一个对象类型,它可以包含我们需要的任意数量的子对象:a featureCollection .

    我看到你正在使用 topojson,topojson.feature返回一个 geojson 对象。在您的情况下,每次使用 topojson 时都会返回一个特征集合。

    为了使用 fitSize/fitExtent 我们需要创建一个包含所有单个特征的 geojson 对象,一个特征集合会这样做,结构如下:

    featureCollection = {
    "type":"FeatureCollection",
    "features": [ ... ]
    }

    我们可以使用以下内容构建特征集合:
    var featureCollection = {type:"FeatureCollection","features":[]}

    for (var i = 0; i < allCountryData.length; i++) {

    objName = allCountryData[i].objects[countries[i]];
    countryData = topojson.feature(allCountryData[i], objName);

    featureCollection.features.push(...countryData.features)

    }

    现在我们可以将这个特征集合传递给 fitSize/fitExtent
    projection.fitSize([width,height],featureCollection);

    应该是这样的:

                    var width = 400; //for simplicity set to fixed value
    var height = 200; //for simplicity set to fixed value

    var projection = d3.geoMercator();

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

    var svg = d3.select("#container").append("svg")
    .classed("svg-content", true)
    .attr("width", width)
    .attr("height", height);

    //Example data
    var countries = ['germany', 'italy', 'switzerland', 'france'];

    function loadJsonFiles() {

    var files = ["https://api.myjson.com/bins/1b0ddz",
    "https://api.myjson.com/bins/11jkvb",
    "https://api.myjson.com/bins/96x1j",
    "https://api.myjson.com/bins/sspzr"];

    var promises = [];
    var allCountryData = [];

    files.forEach(function(url) {
    promises.push(d3.json(url))
    });

    return Promise.all(promises)
    .then(function(countryData) {

    for (var i = 0; i < countryData.length; i++) {

    allCountryData.push(countryData[i]);

    }
    return allCountryData;
    });
    }

    loadJsonFiles().then(function(allCountryData) {

    var allBounds = [];
    var objName;
    var countryData;


    var featureCollection = {type:"FeatureCollection","features":[]}
    for (var i = 0; i < allCountryData.length; i++) {

    objName = allCountryData[i].objects[countries[i]];
    countryData = topojson.feature(allCountryData[i], objName);

    featureCollection.features.push(...countryData.features)

    }

    projection.fitSize([400,200],featureCollection)

    svg.selectAll("path")
    .data(featureCollection.features)
    .enter()
    .append("path")
    .attr("d",path);

    });
    svg {
    border: 1px solid black;
    }
    <script src="https://d3js.org/d3.v5.min.js"></script>
    <script src="https://d3js.org/topojson.v2.min.js"></script>
    <div id="container" class="svg-container"> </div>


    我保留了您的代码,只是我使用了不同的 for 循环(如上所示)来创建特征集合,而不是循环附加每个路径,我使用了输入选择。最后,我更改了大小和位置,使其更适合片段 View 。

    关于javascript - D3.js:为具有多个 geoJSON 文件的 map 设置 fitExtent 或 fitSize(或以编程方式居中和缩放),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56516358/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com