使用svg实现点亮地图效果

Posted by csy on 2018-10-25

前言

产品小姐姐提了个需求,希望实现一个地图,根据数量显示每一块有多少人,并用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节点臃肿

虽然有这么多种方式,但是看着好像都不太理想。:flushed:

第一种,直接使用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
    });
})

地图截图

:sparkles: demo戳这里