今天来让地图动起来!
老样子,先看成果~神秘的非洲大陆~
相信没几个人认识这些国家吧XDDD
我自己觉得地图只要格式对的话,其实用D3.js去绘制不难,
我遇到的难点是要让地图置中 XD
下面就会讲解一下
1.格式 & 地图投影
2.利用SVG或是D3内建fitExtent置中
3.上code
今天很多内容主要参考这一篇:使用d3.js绘制地图
D3读取地图资料有特定格式,要花时间找一下。
这次用地图用的GeoJSON
标准格式,回传让我们可以绘制多边形polygon
的点位置
他会长得像这样:
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"properties": {
"name": "Algeria",
"cartodb_id": 1,
"created_at": "2013-11-12T16:15:59+0100",
"updated_at": "2013-11-12T16:15:59+0100"
},
"geometry": {
"type": "MultiPolygon",
"coordinates": [ //利用这边的座标画地图
[
[
[
8.621624,
36.941797
],
]
]
}
},...
D3有很多投影方式,今天采用的是像Google地图常用的麦卡伦投影
详细原理有点复杂XD 就先略过了
这边有两个方法让地图漂亮置中~
1.SVG viewbox & preserveAspectRatio
用SVG的viewbox
: SVG可视范围,想像SVG是一张大白纸,
viewbox就是告诉SVG
1.我要裁的开始座标
2.我要裁的宽高
而preserveAspectRatio进阶设定比例
这次范例就是设定参数:xMidyMid
让他取中间
我的案例就会是
//html
<svg viewBox="420 130 150 350" //这边我已经算好要裁减的位置了
preserveAspectRatio="xMinYMin"
></svg>
这样D3读取资料後,也不用特别设定translate,
就可以置中罗。
不过手机版还要另外设定。
对於SVG viewbox & preserveAspectRatio有兴趣可以参考这一篇(图文精美!)
SVG 研究之路 (23) - 理解 viewport 与 viewbox
2. D3内建fitExtent API
这个简单, 回传地图左上角座标
&右下叫座标
D3就会帮我们放入中心点罗
projection = d3
.geoMercator()
.fitExtent([[0, 0],[width, height],], data);
// SVG 基本设定
const width = window.innerWidth * 0.7;
const height = window.innerHeight * 0.6;
const svg = d3.select("svg");
// 先把变数设好
let projection
let geoGenerator
let path
//读资料
d3.json( "https://raw.githubusercontent.com/codeforgermany/click_that_hood/master/public/data/africa.geojson"
).then(function (data) {
//投影基本设定,还有置中
projection = d3
.geoMercator()
.fitExtent([[0, 0],[width, height],], data);
geoGenerator = d3.geoPath().projection(projection);
// 画地图
svg
.append("g")
.selectAll("path")
.data(data.features)
.enter()
.append('g')
.append("path")
.attr("fill", "#69b3a2")
.attr("d", geoGenerator)
.style("stroke", "#fff")
.on("mouseover", handleMouseOver)
.on("mouseout", function (d, i) {
d3.select(this).transition().duration(300).attr("fill", "#69b3a2");
d3.selectAll("text")
.transition()
.delay(function(d, i) { return 100; })
.text("");
});
});
//处理滑鼠hover效果
function handleMouseOver(e, d) {
let centroid = geoGenerator.centroid(d); //算出中间点
svg
.append("text")
.text(d.properties.name)
.style("font-size", 30)
.style("font-weight", "bold")
.style("display", "inline")
.attr("transform", "translate(" + centroid + ")")
.style("fill", "black")
.transition()
.delay(function(d, i) { return 100; });
d3.select(this).transition().duration(300).attr("fill", "yellow");
}
D3可以做地图资料好好玩!
今天的code在这里,但还是有小bug,点到文字会一直闪 :
试了一些方法没办法解决,但不要强求将文字放在地图旁边就是一个做法哈
有任何想法欢迎留言!
<<: Android Studio初学笔记-Day29-ButtomNavigationView
比较算符 比较算符可大致列出以下几种常用的: 1. 大於(>)、大於等於(>=)...
在去年的 2021–11–25 那天,Google 终於把 Search Console 的检索统计...
从入职到现在也帮助部门开发了许多的平台和应用服务,而原本虚拟主机的签约也快到期了,然而前阵子除了接触...
接下来我们来谈谈 MVP ( Model-View-Presenter ),在知道 MVC 也只是在...
BottomNavigationView是底部导览的控件,就像line下方的四个选项,今天我会分享B...