数据可视化-D3(V7)交互地图绘制

本文介绍如何使用D3.js库创建一个交互式的中国疫情地图,展示各省份的现有确诊量。通过鼠标悬停在省份上,显示确诊量的提示信息。文章详细解释了代码中涉及的投影设置、地图路径生成、颜色填充以及文字定位等关键步骤,并展示了不同版本D3.js中的一些差异。此外,还提到了南海部分的处理方式以及tooltip的实现方法。
摘要由CSDN通过智能技术生成

用的json文件来源于阿里,实现了简单的交互,即鼠标放在省份上,可以显示该省的现有确诊量。注意领土完整性

DataV.GeoAtlas地理小工具系列

v7版本用的是geoMercator()和geoPath;v3版本用的是geo.mercator()和geo.path()。总归还是版本的坑很容易踩 

center决定了地图投影的位置,scale决定了地图投影的大小。

projection() 是设定生成器的投影函数,把上面定义的投影传入即可。以后,当使用此生成器计算路径时,会自己加入投影的影响。

<script>
//定义地图的投影
var projection = d3.geoMercator()
                   .center([100, 38])
                   .scale(920)
                   .translate([width/2, height/2]);
    
//定义地形路径生成器
var geoPath = d3.geoPath()
                .projection(projection); //设定投影
</script>

因为地图里的省份容易互相重叠(比如香港、广东和澳门),所以在texts里用transform进行了细微的人工调整。

<script>
var texts = svg.selectAll(".texts")                             
               .data(data.features)                
               .enter()
               .append("text")
               .attr("class", "texts") 
               .text((d,i)=>d.properties.name)
               .attr("text-anchor","middle")
               .attr("transform", function(d) {
var centroid = geoPath.centroid(d),
                    x = centroid[0],
                    y = centroid[1];
                    if((d.properties.name=="澳门")||(d.properties.name=="安徽省")
                      ||(d.properties.name=="河北省"))
                      y=y+15;
                    if((d.properties.name=="香港"))
                      y=y+10;
                  //return "translate(" + x + ", " + y + ")";
                                    return `translate(${x},${y})`;
                })
               .attr('fill','999')
               .attr("font-size","8px");  
            });
</script>

 南海部分是直接通过通过img src放到html网页上的。本来想尝试fill到svg的rect里,后来发现不是很方便(意思是我不会)

<img src="南海.png" width="150"/>

tooltip的话之前的博客里也写过,v7是event.pageX,v3是d3.event.pageX

<script>
tooltip.html("现有确诊量:"+t)
       .style("visibility","visible")
       .style("left", (event.pageX + 10) + "px")
       .style("top", (event.pageY -10) + "px")
</script>

全部代码:

<html>  
    <head>  
        <meta charset="utf-8">  
        <title>中国数据地图</title>  
    <style>
      .tooltip {
    position: absolute;
    pointer-events: none;
    font-size: 8px;
    opacity: 1;
}
      .southchinasea {
        stroke: black;
        stroke-width: 1px;
        fill: red;
      }
      img{
        border: 0.3px solid black;
      }
    </style>
    </head> 
  <body>
    <script src="d3.v7.js" charset="utf-8"></script> 
    <script>
      var  width=(window.innerWidth||document.documentElement.clientWidth||document.body.clientWidth)*0.8;
      var  height=(window.innerHeight||document.documentElement.clientHeight||document.body.clientHeight)*0.98;
    
      var svg = d3.select("body").append("svg")
            .attr("width", width)
            .attr("height", height);
      var covid=[591,113,2,0,1,5,238,0,2330,7,392,0,102,2,8,150,0,7,103,15,0,5,212,1,12,0,2,0,16,0,0,260761,0,0,1371462]
      var linear = d3.scaleLinear()
            .domain([990,90000])
            .range([0,255]);

      var color=['#fff7ec','#fee8c8','#fdd49e','#fdbb84',
                    '#fc8d59','#ef6548','#d7301f','#b30000','rgb(153, 0, 0)'];
      
      //定义地图的投影
      var projection = d3.geoMercator()
                   .center([100, 38])
                   .scale(920)
                   .translate([width/2, height/2]);
    
      //定义地形路径生成器
      var geoPath = d3.geoPath()
             .projection(projection); //设定投影
                         
      console.log(geoPath); 
      //颜色比例尺
     

    
      //请求ChinaGeo.json
      d3.json("China.json").then(function(data){           //100000_full.json  A2_100000_full.json
                             
        console.log(data);
                var scaleColor = d3.scaleOrdinal()
                        .domain(d3.range(data.features.length))
                        .range(d3.schemeCategory10);

        var groups = svg.append("g");
        var tooltip=d3.select("body")
                      .append("div")
                      .attr("class","tooltip")
                      .style("background-color","#d3d3d3")
                      .style("border-radius", "3px")
                      .style("padding","5px");
        groups.selectAll("path")
            .data(data.features)
            .enter()
            .append("path")
            .attr("class","province")
            .attr("stroke","#333")
            .attr("stroke-width","0.2px")
            .attr("info",(d,i)=>covid[i])
            .attr("fill",function(d,i){
              if(covid[i]<1)
                return color[0];
              else if(covid[i]<5)
                return color[1];
              else if(covid[i]<20)
                return color[2];
              else if(covid[i]<100)
                return color[3];
              else if(covid[i]<200)
                return color[4];
              else if(covid[i]<500)
                return color[5];
              else if(covid[i]<1000)
                return color[6];
              else if(covid[i]<2000)
                return color[7];
              else
                return color[8];

            })

            .attr("d",(d,i)=>geoPath(d))  //使用路径生成器
            .on("mouseover",function(d,i){
              console.log(i);
              const change=d3.select(this)
                .attr("stroke-width","1.5px")
              var t=change.attr("info")
              tooltip.html("现有确诊量:"+t)
                     .style("visibility","visible")
                     .style("left", (event.pageX + 10) + "px")
                     .style("top", (event.pageY -10) + "px")

            })
            .on("mouseout",function(d,i){
              console.log(i);
              d3.select(this)
                .attr("stroke-width","0.2px")
              tooltip.style('visibility', 'hidden')
            });
                
          
          var texts = svg.selectAll(".texts")                             
                .data(data.features)                
                .enter()
                .append("text")
                .attr("class", "texts") 
                .text((d,i)=>d.properties.name)
                .attr("text-anchor","middle")
                .attr("transform", function(d) {
                  var centroid = geoPath.centroid(d),
                    x = centroid[0],
                    y = centroid[1];
                    if((d.properties.name=="澳门")||(d.properties.name=="安徽省")
                      ||(d.properties.name=="河北省"))
                      y=y+15;
                    if((d.properties.name=="香港"))
                      y=y+10;
                  //return "translate(" + x + ", " + y + ")";
                                    return `translate(${x},${y})`;
                })
                .attr('fill','999')
                .attr("font-size","8px");  
            });
          var title=svg.append("text")
                .text("新冠疫情大数据报告")
                .attr("x",width/2-100)
                .attr("y",40)
                .attr("font-size","30")
                .attr("fill","#555")
          var title=svg.append("text")
                .text("5月22日,2022年")
                .attr("x",width/2-60)
                .attr("y",70)
                .attr("font-size","20")
                .attr("fill","#555")


</script>
 <img src="南海.png" width="150"/>
    </body>  
</html>  

  • 3
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值