d3.js choropleth map - 如何将多个属性从CSV映射到JSON,以便在工具提示中使用它?

时间:2015-12-15 15:58:27

标签: javascript json csv d3.js

我有一个用d3.js构建的等值线图。我将我的data.csv中的'Total_Score'属性映射到我的JSON文件中的'id'属性,我正在使用该分数为状态着色。我也在使用工具提示鼠标悬停时显示它。

但是,我希望能够显示我的CSV文件中的其他属性。还有四个 - “排名”,“第一”,“第二”和“第三”。我是否还必须为每个人创建一张地图?我从未映射过多个,所以任何指导或示例都会非常感激。

谢谢!

Here is a plunker for reference.

以下是代码:

<!DOCTYPE html>
    <html lang="en">
        <head>
            <meta charset="utf-8">
            <title>Worst Drivers</title>
            <script src="http://d3js.org/d3.v3.min.js"></script>
            <script src="d3.tip.js"></script>
            <style type="text/css">
                body{
                    background:#333;
                    font-family:Helvetica, Arial, sans-serif;
                    font-size:13px;
                    color:#fff;
                    padding:0px;
                    margin:0px;
                }
                h1{
                    margin:50px 0px 0px;
                    text-align:center;
                    font-size:30px;
                    font-weight:normal;
                }
                h2{
                    margin:0px;
                    padding:0px;
                }
                h4{
                    font-size:16px;
                }
                a{
                    text-decoration: none;
                    color: #2bbe8c;
                }
                #panel{
                    background:#fff;
                    color:#111;
                    width:27%;
                    height:100%;
                    float:right;
                    padding:3%;
                }
                #map{
                    width:66%;
                    float:left;
                }
                .sources{
                    font-size:12px;
                }
                .d3-tip{
                    background:#000;
                    opacity:.7;
                    padding:20px;
                    border-radius:3px;
                }
                .statename{
                    font-size:16px;
                }
                .mainno{
                    font-size:14px;
                }
                #legend{
                    position:absolute;
                    width:66%;
                    height:20px;
                }
                #legendinner{
                    margin:0 auto;
                    position:relative;
                    width:245px;
                }
                .legendleft{
                    width:50px;
                    float:left;
                    margin:0px;
                }
                .legendright{
                    width:50px;
                    float:right;
                    text-align:right;
                    margin:0px;
                }
            </style>
        </head>
        <body>
            <div id="container">
                <div id="map">
                    <div id="legend">
                        <div id="legendinner">
                            <svg width="250" height="15">
                                <rect x="0" y="0" width="50" height="10" fill="#041e47"></rect>
                                <rect x="50" y="0" width="50" height="10" fill="#063685"></rect>
                                <rect x="100" y="0" width="50" height="10" fill="#0449bb"></rect>
                                <rect x="150" y="0" width="50" height="10" fill="#055ced"></rect>
                                <rect x="200" y="0" width="50" height="10" fill="#5092ff"></rect>
                            </svg>
                            <p class="legendleft">Most</p>
                            <p class="legendright">Least</p>
                        </div>
                    </div>
                </div>
            </div>

            <script type="text/javascript">

                //Width and height
                var w = Math.max(window.innerWidth) / 3 *2;
                var h = Math.max(window.innerHeight) - 100;

                //Create SVG element
                map  = d3.select("#map")
                         .append("svg")
                                 .attr("id", "usstates")
                         .attr("width",  w)
                         .attr("height", h);

          var maph = document.getElementById('usstates').clientHeight;

                d3.select("#legend")
                .style("top", maph + 150 + "px");

                //Define map projection
                var p = d3.geo.albersUsa()
                        .translate([w/2, h/2])
                        .scale([1000]);

                //Define path generator
                var path = d3.geo.path()
                        .projection(p);



              //load the geoJSON file for drawing the map
                d3.json("states.json", function(error, states) {

                    var newDict = {}; //mapping for choropleth
                    var tip = d3.tip()
                            .attr('class', 'd3-tip')
                            .offset([40, 0])
                            .html(function(d,i) { 
                                return "<span class='statename'>" + d.properties.name + "</span>" + 
                                "<hr/>" +
                                "<span class='mainno'>Total Score: " + newDict[d.id] + 
                                "<br/>rank: </span>" +
                                "<hr/>" + 
                                "First: " +
                                "<br/>Second: " +
                                "<br/>Third: " ;
                            })

                    var mapstates = map.append("svg:g")
                            .attr("id", "states")
                            .style("fill", "#dedee0")
                            .style("stroke", "#aaa")
                            .style("stroke-width", .5);

                            mapstates.call(tip);

                    mapstates
                                    .selectAll("path")
                                    .data(states.features)
                                .enter().append("path")
                                .attr("d", path);

                        d3.csv("data.csv", function(error, data) {

                            data.forEach(function(d){
                              d.rank = + d.rank;
                                d.Total_Score   = +d.Total_Score;
                              newDict[d.id] = +d.Total_Score;
                            });

                            var minValue = d3.min(data, function(d,data) { return d.Total_Score; });
                            var maxValue = d3.max(data, function(d,data) { return d.Total_Score; });

                            //Quantize scale for map
                            var color = d3.scale.quantize()
                                    .domain([minValue, maxValue])
                                    .range(["#041e47", "#063685", "#0449bb", "#055ced", "#5092ff"]);



                            mapstates
                                            .selectAll("path")
                                        .attr("d", path)
                                            .on('mouseover', function(d) {

                                               d3.select(this).style('fill-opacity', .75);
                                            })
                                            .on('mouseout', function(d){
                                                d3.select(this).style("fill-opacity", 1);
                                            })
                                            .on('mouseover', tip.show)
                                            .on('mouseout', tip.hide)
                                            .attr("class", function(d){return newDict[d.id];})
                                            .attr("fill", function(d) { return color(newDict[d.id]); })
                                            .text("heyo");

                            mapstates.selectAll("text")
                                            .data(states.features)
                                            .enter()
                                            .append("text")
                                            .html(function(d){
                                                 return d.properties.abbr + ": " + newDict[d.id] ;
                                            })
                                            .attr("x", function(d){
                                                return path.centroid(d)[0];
                                            })
                                            .attr("y", function(d){
                                                 return  path.centroid(d)[1];
                                            })
                                            .attr("text-anchor","middle")
                                            .attr('font-size',11)
                                            .attr('font-weight', 'normal');

                        }); //close csv
                }); // close json

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

data.csv文件:

"State","id","first","second","third","TotalScore","rank"
    "Alabama",1,15,24,29,113,18
    "Alaska",2,22,51,50,195,49
    "Arizona",4,14,28,41,109,14
    "Arkansas",5,5,21,43,141,28
    "California",6,42,26,39,146,33
    "Colorado",8,33,4,24,101,11
    "Connecticut",9,48,44,9,185,47
    "Delaware",10,21,31,12,74,7
    "District of Columbia",11,51,8,32,139,27
    "Florida",12,19,29,30,131,24
    "Georgia",13,28,11,46,147,34
    "Hawaii",15,20,33,6,70,5
    "Idaho",16,27,20,36,152,38
    "Illinois",17,39,39,10,125,22
    "Indiana",18,36,19,34,165,42
    "Iowa",19,25,38,48,205,50
    "Kansas",20,17,15,47,151,37
    "Kentucky",21,6,2,49,131,24
    "Louisiana",22,7,5,19,71,6
    "Maine",23,26,10,17,103,12
    "Maryland",24,41,50,18,141,28
    "Massachusetts",25,50,37,8,156,39
    "Michigan",26,37,42,37,179,45
    "Minnesota",27,49,34,35,205,50
    "Mississippi",28,8,12,26,111,17
    "Missouri",29,24,18,13,91,10
    "Montana",30,3,6,1,59,2
    "Nebraska",31,29,16,7,141,28
    "Nevada",32,30,14,14,79,8
    "New Hampshire",33,43,46,33,190,48
    "New Jersey",34,46,43,21,160,40
    "New Mexico",35,11,27,42,109,14
    "New York",36,40,36,20,143,31
    "North Carolina",37,23,35,23,109,14
    "North Dakota",38,4,3,2,66,4
    "Ohio",39,35,22,15,135,26
    "Oklahoma",40,9,1,31,87,9
    "Oregon",41,34,49,45,184,46
    "Pennsylvania",42,18,32,25,105,13
    "Rhode Island",44,44,48,4,147,34
    "South Carolina",45,1,30,3,54,1
    "South Dakota",46,10,7,11,114,20
    "Tennessee",47,13,25,27,143,31
    "Texas",48,12,23,5,63,3
    "Utah",49,45,9,51,169,44
    "Vermont",50,31,13,40,113,18
    "Virginia",51,38,40,38,163,41
    "Washington",53,47,47,22,165,42
    "West Virginia",54,2,45,44,116,21
    "Wisconsin",55,32,17,16,130,23
    "Wyoming",56,16,41,28,149,36

(我无法在此处粘贴states.json文件,因为它超出了帖子允许的正文大小,但如果您转到Plunker,则可以看到它。)

1 个答案:

答案 0 :(得分:1)

您可以创建对象并将其放入newDict中。任何其他收藏也可以。

下面是添加具有排名和分数属性的新对象的代码。

data.forEach(function(d){
  d.rank = d.rank;
  d.Total_Score = d.Total_Score;
  newDict[d.id] = {rank:d.rank, score:d.Total_Score};
});

然后可以像普通对象一样使用它们。

mapstates
    .selectAll("path")
    .attr("d", path)
    .on('mouseover', function(d) {
        d3.select(this).style('fill-opacity', .75);
    })
    .on('mouseout', function(d){
        d3.select(this).style("fill-opacity", 1);
    })
    .on('mouseover', tip.show)
    .on('mouseout', tip.hide)
    .attr("class", function(d){return newDict[d.id];})
    attr("fill", function(d) { return color(newDict[d.id].score); });

添加任意数量的值是data.forEach闭包的简单补充。

你的傻瓜的Here's my fork实施了一些改变。