如何在动态改变投影后居中d3.js地图?

时间:2014-09-07 09:22:06

标签: javascript d3.js map

我正在尝试创建一个地图,用户可以在其中选择一个新投影,并且它将在运行中应用。

这是我做的(你可以找到一个演示here

<!DOCTYPE html>
<html>
<head>

    <meta content="utf-8">
    <style type="text/css">

svg {
  border: 1px solid #ccc;
}

path {
  fill: #ccc;
  stroke: #fff;
  stroke-width: .5px;
}

path:hover {
  fill: #00AEEC;
}

#projectionList {

    width: 200px; 
    height: 500px; 
    float: left; 

    border: 1px solid grey;

}



    </style>

</head>
<body>

<div id="mainContainer">

    <div id="projectionList">

    </div>

    <div id="graphContainer">

    </div>

</div>


<script src="http://d3js.org/d3.v3.min.js"></script>
<script src="http://d3js.org/topojson.v1.min.js"></script>

<script type="text/javascript">



    // d3.js graph 

    var width = 900,
    height = 500;

    var path = d3.geo.path();

    var svg = d3.select("#graphContainer").append("svg")
        .attr("width", width)
        .attr("height", height);

    d3.json("tunisia.json", function(error, topology) {

    console.log(topology); 


    //console.clear();

    var featureCollection = topojson.feature(topology, topology.objects.governorates);
    var bounds = d3.geo.bounds(featureCollection);

    var centerX = d3.sum(bounds, function(d) {return d[0];}) / 2,
      centerY = d3.sum(bounds, function(d) {return d[1];}) / 2;

    var projection = d3.geo.mercator()
        .scale(3000)
        .center([centerX, centerY]);

    path.projection(projection);

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


    });


    //end of d3.js graph 




        var selectProjection = {projection_list: []}; 

        // add the list of supported projection 

        /*schema of objects: 

            {
                id: "unique_int", 
                projection_name: "a name", 
                projection_function: "a function name", 
                projection_description: "a description"
            }
        */

        //add first projection 
        selectProjection.projection_list.push({
            id: 1, 
            projection_name: "azimuthalEqualArea", // to be updated with a more descriptive name 
            projection_function: "azimuthalEqualArea", 
            projection_description: "azimuthalEqualArea" // to be updated with more detailed description 
        }); 

        // add second projection 

        selectProjection.projection_list.push({
            id: 2, 
            projection_name: "conicConformal", // to be updated with a more descriptive name 
            projection_function: "conicConformal", 
            projection_description: "conicConformal" // to be updated with more detailed description 
        });

        // add thrid projection 

        selectProjection.projection_list.push({
            id: 3, 
            projection_name: "equirectangular", // to be updated with a more descriptive name 
            projection_function: "equirectangular", 
            projection_description: "equirectangular" // to be updated with more detailed description 
        });



        selectProjection.projection_list.push({
            id: 4, 
            projection_name: "Mercator", // to be updated with a more descriptive name 
            projection_function: "mercator", 
            projection_description: "mercator" // to be updated with more detailed description 
        });
        // the above storage method is used temporary in order to leverage a demo, in production mode, there will be a database table to hold these information 



        function set_projection(option) {
          proj = option.value



          projection = eval("d3.geo."+proj+"().scale(500);");

          path = d3.geo.path()
            .projection(projection);

          svg.selectAll("path").transition()
              .duration(1000)
               .attr("d", path);

          /*var link = "https://github.com/mbostock/d3/wiki/Geo-Projections#wiki-" + proj
          d3.selectAll("div#current_proj_info").html("Current projection: <a href=\""+link+"\">"+option.text+"</a>");*/
        }



        function apply_projection(e){
            // applying a new projection 
            set_projection(e.target[e.target.selectedIndex]); 
        }

        var newSelect = document.createElement("select");
        newSelect.id = "selectProjection"; 
        newSelect.onchange = apply_projection; 



        for (var i = selectProjection.projection_list.length - 1; i >= 0; i--) {
            console.log(selectProjection.projection_list[i].projection_name); 

            newSelect[newSelect.length] = new Option(selectProjection.projection_list[i].projection_name, selectProjection.projection_list[i].projection_function, false, false); 

        };

        console.log("newSelect content");
        console.log(newSelect);

        document.getElementById('projectionList').appendChild(newSelect);

</script>

</body>
</html>

问题在于,当我尝试在应用新投影后缩放图形时,它会超出div的可见区域。

请你检查一下是什么问题。

0 个答案:

没有答案