前言
产品小姐姐提了个需求,希望实现一个地图,根据数量显示每一块有多少人,并用6种深浅不一颜色的颜色表示。奇形怪状的点击域+改变图片的颜色,自然而然就想到用SVG啦。
在Web中显示SVG有六种方式
-
直接使用<svg>元素
- 将SVG图像作为背景图像嵌入
1
background-image:url(test.svg)
- 使用<img>元素来嵌入SVG图像
1
<img src="test.svg">
- 使用<iframe>元素来嵌入SVG图像
1
<iframe src="test.svg"></iframe>
- 使用<embed>元素来嵌入SVG图像
1
<embed src="test.svg"></embed>
- 使用<object>元素来嵌入SVG图像
1
<object type="image/svg+xml" data="test.svg"></object>
CSS中使用内联SVG可以解决HTML节点臃肿
虽然有这么多种方式,但是看着好像都不太理想。
第一种,直接使用SVG元素,样式和脚本不受SVG文件限制,可以放在当前文档任意位置、可以当前文档直接修改、移植方便、没有跨域问题。感觉好像挺完美的。但是我大中华辽阔的国土有34个省级行政区域,在页面直接使用34个SVG会导致HTML非常非常臃肿。
第二种,将SVG图像作为背景图像嵌入。background: url(demo.svg),需要另外再存一个xxx.svg。存34个xxx.svg太麻烦了,而且请求多次。可以用Data-URI来引用小文件,比如
1
2
3
4
background: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdm
ciIHZpZXdCb3g9IjAgMCA3NTAgNDAwIj4gCQkJPHBhdGggZD0iTTAsMCBMNzUwL
DAgTDc1MCw0MDAgTDM4OCw0MDAgTDM3NSwzODcsIEwzNjIsNDAwIEwwLDQw
MFoiIGZpbGw9IiMwZjAiPjwvcGF0aD4gCQk8L3N2Zz4=);
第二种,第三种,第四种,第五种,第六种都是通过url来加载SVG图像。如果要根据数据来修改颜色,好像不太方便。
强大的矢量图形库 Raphael.js
可以将SVG的路径全部存在一个json数组里。创建Raphael对象,设置画布大小。最后For循环遍历SVG路径逐个引入。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//创建Raphael对象
let map = new Raphael(document.getElementById('map'))
//设置画布大小
map.setViewBox(0, 0, 471, 389.5)
//遍历svg路径
this.id.forEach((item, idx) => {
people = parseInt(province[item]) //人数
fill = this.getColor(that.darkColor, people) //填充色
let pathTmp = map.path(that.MapJson[idx])
pathTmp.attr({fill: fill,'stroke-width': 0})
.data("idx", idx)
.data("id", item)
.data("dark", fill)
.data("people", people)
.click(function(e) {
//TODO:点击事件 弹出tips
});
})