Vue + D3 动态可视化图实现之五:世界地图

2022/11/10 声明

(这篇文章也被下架了)
这个项目只是以 GTD 数据库为例做数据的统计及可视化,不涉及对任何具体事件的分析和评论,希望能恢复发表!文中地图数据取自互联网,不代表立场,博主坚持拥护我国领土完整!

GTD数据分析及可视化项目的第五张图表,项目总体介绍见这篇文章

最终效果

在这里插入图片描述

数据集

统计目标是1970-2018年各国恐怖袭击情况,不用分年份,按国家统计即可。
在这里插入图片描述

实现

绘制世界地图的方案是使用world.geojson文件,这部分有比较完整的教程,见项目总体介绍的推荐学习网站。

		mounted() {
			// The svg
			svg = d3.select('#choropleth-graph')
				.append("svg")
				.attr("width", width)
				.attr("height", height)
				.on('mousemove', mouseMove)
			
			// 悬浮提示信息
			tooltip = d3.select('#tooltip')
				.style('display', 'none');

			projection = d3.geoMercator()
				.scale(180)
				.center([0, 20])
				.translate([width / 2, height / 2]);

			path = d3.geoPath(projection);
			
			// 放缩
			zoom = d3.zoom()
				.scaleExtent([1, 8])
				.on("zoom", zoomed);
		},

draw函数中,主要考虑两个问题。一是鼠标移动事件,根据鼠标位置确定所在国家,进而获得该国信息并展示。二是染色,可以按指标比例染色,但这样可能出现和词云图一样差距过大的问题,故可以改进为按若干档区间染色,这里使用了6档阈值,阈值由统计数据按比例取得。

			draw() {
				// 消除全部地图会闪动
				d3.select("#choropleth-graph").selectAll("g").remove()

				let mouseOver = function(e) {
					//console.log(e.toElement);
					d3.selectAll(".Country")
						.transition()
						.duration(200)
						.style("opacity", .5)
					d3.select(e.toElement)
						.transition()
						.duration(200)
						.style("opacity", 1)
						.style("stroke", "black")
					tooltip.style('display', 'block');
					let cid = e.toElement.id
					//console.log(cid);

					let country = rawData.find(function(item) {
						return item.name == cid
					})
					// 有些国家没有记录,不在数据表中
					if (typeof(country) == 'undefined') {
						country = {
							name: cid,
							killed: 0,
							attacks: 0
						}
					}
					let text = country.name + '\n\n袭击数: ' + country.attacks + '\n死亡数: ' + country.killed
					tooltip.text(text)
				}

				let mouseLeave = function(e) {
					d3.selectAll(".Country")
						.transition()
						.duration(200)
						.style("opacity", .8)
					e.fromElement.style.setProperty('stroke', 'transparent')
					tooltip.style('display', 'none');
				}

				d3.json("world.geojson").then(function(topo) {
					//等比例
					/*
					color = d3.scaleSequential()
						.domain(d3.extent(Array.from(dataMap.values())))
						.interpolator(d3.interpolateYlGnBu)
						.unknown("#ccc")
					*/
					//*
					// 6档阈值
					color = d3.scaleThreshold()
						.domain(curScale)
						.range(d3.schemeOranges[7]);
					//*/;
				g = svg.append("g")
				g
					.selectAll("path")
					.data(topo.features)
					.enter()
					.append("path")
					// draw each country
					.attr("d", path)
					// set the color of each country
					.attr("fill", function(d) {
						d.total = dataMap.get(d.id) || 0;
						return color(d.total);
					})
					.style("stroke", "transparent")
					.attr("class", d => "Country")
					.attr("id", d => d.properties.name)
					.style("opacity", .8)
					.on("mouseover", mouseOver)
					.on("mouseleave", mouseLeave)
				
				svg.call(zoom)
				})
			},

源码

项目总体介绍底部项目链接。本图源码为src/components/Choropleth.vue文件。

  • 6
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值