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

d3.js choropleth map --How do I map more than one property from CSV to JSON, so I can use it in a tooltip?

本文关键字:JSON 工具提示 映射 CSV map choropleth js 属性 d3      更新时间:2023-09-26

我有一个用d3.js构建的choropleth映射。我将data.csv中的"Total_Score"属性映射到JSON文件中的"id"属性,并使用该分数为状态着色。我还在鼠标悬停上用工具提示显示它。

但是,我也希望能够显示CSV文件中的其他属性。还有四个——"排名"、"第一"、"第二"answers"第三"。我也必须为每一个创建一个地图吗?我从未绘制过多个地图,所以任何指导或示例都将不胜感激。

谢谢!

这里有一个plunker供参考。

这是代码:

<!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,你可以看到它。)

您可以创建对象并将它们放在您的newDict中。任何其他的收藏品也可以。

下面是添加一个具有rank和score属性的新对象的代码。

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); });

添加任意数量的值都是对数据的简单添加。对于每个闭包。

这是我对你的一些改变的看法。