【D3.js - v5.x】(7)绘制地图 | Geo布局 | 完整代码

简介: 【D3.js - v5.x】(7)绘制地图 | Geo布局 | 完整代码

地图

数据可视化中,地图是很重要的一部分。很多情况会与地图有关联,如中国各省的人口多少,GDP多少等,都可以和地图联系在一起。

地图数据的获取

制作地图需要 JSON 文件,将 JSON 的格式应用于地理上的文件,叫做 GeoJSON 文件。本文就是用这种文件绘制地图。

那么如何获取中国地图的 GeoJSON 文件呢? 如下链接,打开并下载至本地,并命名为ChinaGeoFull.json,后面实现会用到。

https://geo.datav.aliyun.com/areas_v2/bound/100000_full.json

投影函数

由于 GeoJSON 文件中的地图数据,都是经度和纬度的信息。它们都是三维的,而要在网页上显示的是二维的,所以要设定一个投影函数来转换经度纬度。如:

var projection = d3.geoMercator()
      .center([107, 31])
      .scale(850)
      .translate([width/2, height/2]);

文档: https://www.d3js.org.cn/document/d3-geo/#projections

其中,

  • center() 设定地图的中心位置,[107,31] 指的是经度和纬度。
  • scale() 设定放大的比例。
  • translate() 设定平移。

地理路径生成器

为了根据地图的地理数据生成 SVG 中 path 元素的路径值,需要用到d3.geoPath([projection[, context]),称它为地理路径生成器。

文档:https://www.d3js.org.cn/document/d3-geo/#paths

使用默认的设置创建一个新的地理路径生成器. 如果指定了 projection, 则设置 当前投影. 如果指定了 context 则设置当前 当前上下文.

var path = d3.geoPath(projection)

向服务器请求文件并绘制地图

 d3.json("./ChinaGeoFull.json").then(function(data){
        console.log(data)
        svg.selectAll("g")
            .data(data.features)
            .enter()
            .append("g")
            .append("path")
            .attr('d',path)//使用地理路径生成器
            .attr("stroke","#000")
            .attr("stroke-width",1)
            .attr("fill", function(d,i){
                return color[i%10];
            })
            .on("mouseover",function(d,i){
                d3.select(this).attr("fill","yellow");
            })
            .on("mouseout",function(d,i){
                d3.select(this).attr("fill",color(i));
            });
      //添加坐标
      svg.selectAll("g")
         .append('text')
         .attr('font-size', 12)
         .attr('text-anchor', 'middle')
         .attr('x', d => {
          var position = projection(d.properties.centroid || [0, 0]);
          return position[0];
         })
         .attr('y', d => {
          var position = projection(d.properties.centroid || [0, 0]);
          return position[1];
        })
        .attr('dy', d => {
        //澳门和香港重合了,挤到一起了
          if (d.properties.name === '澳门') {
            return 15;
          }
        })
        .text(d => d.properties.name);
      })

完整代码

<body>
    <svg width="1000" height="1000"></svg>
    <script>
      var marge = {top:60,bottom:60,left:60,right:60}
      var svg = d3.select("svg")
      var width = svg.attr("width")
      var height = svg.attr("height")
      var g = svg.append("g").attr("transform","translate("+marge.top+","+marge.left+")");
      //投影函数
      var projection = d3.geoMercator()
      .center([107, 31])
      .scale(800)
      .translate([width/2, height/2]);
      //路径
      var path = d3.geoPath(projection);
      var color = d3.schemeCategory10;
      d3.json("./ChinaGeoFull.json").then(function(data){
        console.log(data)
        svg.selectAll("g")
            .data(data.features)
            .enter()
            .append("g")
            .append("path")
            .attr('d',path)//使用地理路径生成器
            .attr("stroke","#000")
            .attr("stroke-width",1)
            .attr("fill", function(d,i){
                return color[i%10];
            })
            .on("mouseover",function(d,i){
                d3.select(this).attr('opacity', 0.5);
            })
            .on("mouseout",function(d,i){
                d3.select(this).attr('opacity', 1);
            });
      //添加坐标
      svg.selectAll("g")
         .append('text')
         .attr('font-size', 12)
         .attr('text-anchor', 'middle')
         .attr('x', d => {
          var position = projection(d.properties.centroid || [0, 0]);
          return position[0];
         })
         .attr('y', d => {
          var position = projection(d.properties.centroid || [0, 0]);
          return position[1];
        })
        .attr('dy', d => {
        //这里为什么这么写呢,因为澳门和香港重合了,挤到一起了。
          if (d.properties.name === '澳门') {
            return 15;
          }
        })
        .text(d => d.properties.name);
      })
    </script>
</body>



相关文章
|
4月前
|
JavaScript 前端开发 安全
【逆向】Python 调用 JS 代码实战:使用 pyexecjs 与 Node.js 无缝衔接
本文介绍了如何使用 Python 的轻量级库 `pyexecjs` 调用 JavaScript 代码,并结合 Node.js 实现完整的执行流程。内容涵盖环境搭建、基本使用、常见问题解决方案及爬虫逆向分析中的实战技巧,帮助开发者在 Python 中高效处理 JS 逻辑。
|
6月前
|
JavaScript 前端开发 算法
流量分发代码实战|学会用JS控制用户访问路径
流量分发工具(Traffic Distributor),又称跳转器或负载均衡器,可通过JavaScript按预设规则将用户随机引导至不同网站,适用于SEO优化、广告投放、A/B测试等场景。本文分享一段不到百行的JS代码,实现智能、隐蔽的流量控制,并附完整示例与算法解析。
174 1
|
7月前
|
JavaScript 前端开发
怀孕b超单子在线制作,p图一键生成怀孕,JS代码装逼娱乐
模拟B超单的视觉效果,包含随机生成的胎儿图像、医疗文本信息和医院标志。请注意这仅用于前端开发学习
|
7月前
|
JavaScript
JS代码的一些常用优化写法
JS代码的一些常用优化写法
128 0
|
9月前
|
存储 JavaScript 前端开发
在NodeJS中使用npm包进行JS代码的混淆加密
总的来说,使用“javascript-obfuscator”包可以帮助我们在Node.js中轻松地混淆JavaScript代码。通过合理的配置,我们可以使混淆后的代码更难以理解,从而提高代码的保密性。
860 9
|
10月前
|
前端开发 JavaScript
【Javascript系列】Terser除了压缩代码之外,还有优化代码的功能
Terser 是一款广泛应用于前端开发的 JavaScript 解析器和压缩工具,常被视为 Uglify-es 的替代品。它不仅能高效压缩代码体积,还能优化代码逻辑,提升可靠性。例如,在调试中发现,Terser 压缩后的代码对删除功能确认框逻辑进行了优化。常用参数包括 `compress`(启用压缩)、`mangle`(变量名混淆)和 `output`(输出配置)。更多高级用法可参考官方文档。
710 11
|
12月前
|
人工智能 程序员 UED
【01】完成新年倒计时页面-蛇年新年快乐倒计时领取礼物放烟花html代码优雅草科技央千澈写采用html5+div+CSS+JavaScript-优雅草卓伊凡-做一条关于新年的代码分享给你们-为了C站的分拼一下子
【01】完成新年倒计时页面-蛇年新年快乐倒计时领取礼物放烟花html代码优雅草科技央千澈写采用html5+div+CSS+JavaScript-优雅草卓伊凡-做一条关于新年的代码分享给你们-为了C站的分拼一下子
610 21
【01】完成新年倒计时页面-蛇年新年快乐倒计时领取礼物放烟花html代码优雅草科技央千澈写采用html5+div+CSS+JavaScript-优雅草卓伊凡-做一条关于新年的代码分享给你们-为了C站的分拼一下子
|
12月前
|
前端开发 JavaScript
【02】v1.0.1更新增加倒计时完成后的放烟花页面-优化播放器-优化结构目录-蛇年新年快乐倒计时领取礼物放烟花html代码优雅草科技央千澈写采用html5+div+CSS+JavaScript-优雅草卓伊凡-做一条关于新年的代码分享给你们-为了C站的分拼一下子
【02】v1.0.1更新增加倒计时完成后的放烟花页面-优化播放器-优化结构目录-蛇年新年快乐倒计时领取礼物放烟花html代码优雅草科技央千澈写采用html5+div+CSS+JavaScript-优雅草卓伊凡-做一条关于新年的代码分享给你们-为了C站的分拼一下子
387 14
【02】v1.0.1更新增加倒计时完成后的放烟花页面-优化播放器-优化结构目录-蛇年新年快乐倒计时领取礼物放烟花html代码优雅草科技央千澈写采用html5+div+CSS+JavaScript-优雅草卓伊凡-做一条关于新年的代码分享给你们-为了C站的分拼一下子
|
10月前
|
JavaScript 前端开发 算法
JavaScript 中通过Array.sort() 实现多字段排序、排序稳定性、随机排序洗牌算法、优化排序性能,JS中排序算法的使用详解(附实际应用代码)
Array.sort() 是一个功能强大的方法,通过自定义的比较函数,可以处理各种复杂的排序逻辑。无论是简单的数字排序,还是多字段、嵌套对象、分组排序等高级应用,Array.sort() 都能胜任。同时,通过性能优化技巧(如映射排序)和结合其他数组方法(如 reduce),Array.sort() 可以用来实现高效的数据处理逻辑。 只有锻炼思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~
|
10月前
|
JavaScript 前端开发 API
JavaScript中通过array.map()实现数据转换、创建派生数组、异步数据流处理、复杂API请求、DOM操作、搜索和过滤等,array.map()的使用详解(附实际应用代码)
array.map()可以用来数据转换、创建派生数组、应用函数、链式调用、异步数据流处理、复杂API请求梳理、提供DOM操作、用来搜索和过滤等,比for好用太多了,主要是写法简单,并且非常直观,并且能提升代码的可读性,也就提升了Long Term代码的可维护性。 只有锻炼思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~