添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

1.ECharts使用SVG做地图

ECharts是一个基于 JavaScript 的开源可视化图表库,在很多大屏中都有使用到,但大多数情况都是用来制作图表,柱状图、折线图、饼图等等。地图也是它其中的一个模块,毕竟不像OpenLayer、Leaflet这样专业做地图的组件库,所以能实现的 功能都十分基础 ,但它 容易入手 ,配置项也很少,在使用时我们需要综合考虑需求来选择是否采用ECharts。

普通的引入JSON创建地图很常见也很简单,看 文档 应该是没问题的,并且很多官方的示例也都是用引入JSON文件的方式创建地图的。在这里我推荐几个我比较常用的网站吧。

阿里云DataV地理小工具

DataV.GeoAtlas地理小工具系列

  • 第一个功能:范围选择器。用于下载行政区划边界数据,最小粒度到区级,使用比较简单。包括中国所有省份及地市的JSON和SVG文件,可以使用api引入也可以下载成文件引入。
  • 第二个功能:边界生成器。用于生产一个几何面的边界数据,支持有多种编辑功能。可以导入多份JSON或其他格式地理数据将其合并为一个JSON或SVG文件,也可以执行交集差集这样简单的布尔运算。另外还可以执行在地图上画几何图,随机生产点,增加属性等操作,同样也能导出为JSON或SVG文件。
  • 第三个功能:层级生成器。用于生成自定义下钻区域的树形结构数据。这个比较常用于制作下钻地图,可以编辑不同区域的层级关系用于下钻。例如需要创建一个叫江浙沪的区域,需要从京津冀大区域一层层下钻到其中一个地市的某个区,这就需要使用层级生成器生成JSON文件。
  • 这个时候我才注意到设计图上不只有倒影,还有第二、三层之间有竖条纹,这是3D地图的一个边缘纹理效果,所以我开始准备学习使用three.js来制作,或者ECharts GL来实现3D效果,但这次的地图所需具备的功能就只是在地图上展示一些点而已,并不要求有其他功能,所以我就想在这样一个地图上用WebGL是否有点杀鸡用牛刀,因为这就像我开始说的需要综合考虑需求来选取最合适的方案。所以经过一番考虑和尝试,也放弃了WebGL。

    这时候我发现了ECharts可以支持 以SVG图为底图 来注册地图

    它所用的方法其实上就是把一张SVG图作为底图,然后通过SVG图代码中一些属性来识别不同区域,最终达到和GeoJSON相同的效果。这样来说我是不是就可以把UI提供的图直接拿来用,加以改造使其具备地图的属性。看起来似乎是最优的解决方案,确定路线后就准备往前走了。但是SVG作为底图官方并没有画大篇幅进行讲解,搜索到的实例也十分有限,所以只能自己在摸索中前进。

    在这个过程中也遇到了几个坑和难点,提供了几个我自己的解决方案,如果有更好的可以和我探讨,我踩过的坑也希望大家不要再踩了。

    注册SVG地图

    SVG底图的引入和JSON一样,可以使用 import 方式引入,也支持 require 方式引入,前一种方式适用于不变的文件引入,放在开头在编译时调用,后者是可以动态变化的,在运行过程中才加以调用。就例如我需要根据点击区域实现调用不同的SVG底图,这时就需要使用 require 方式动态引入,如下所示:

    const mapSVG = require('../../assets/images/map/' + this.cityName + '.svg')
    

    但是注册地图就比JSON要麻烦一些了,它不能直接使用echarts.registerMap('map', mapJSON) 进行注册,这当时让我卡了好久,必须严格按照官网上的步骤一步步操作。

    // 首先需要jquery方式获取刚才引入的SVG底图
    $.get(mapSVG, function (mapSVG) {
        // 然后才能进行地图注册
        echarts.registerMap('cityMap', {svg: mapSVG});
            // 下面就是常规的chart初始化配置操作
        var chart = echarts.init(document.getElementById('map'))。
        chart.setOption({
            geo: [{
                // 引用注册过的底图
                map: 'cityMap',
    

    SVG编辑

    如果引入的不是DataV里下载的SVG底图,而只是引入UI给的普通SVG图的话是没有交互效果的,它就只是一张图,和普通的背景没什么两样,在官网中有专门提到这类具名元素

    👉🏼 如果要控制 SVG 中的某些元素,或者让某些元素能交互,我们首先要在 SVG 中标记这些元素:在这些元素上添加 name属性(下文称此类添加过 name属性的元素为:“具名元素”)。许多功能都依赖于对元素的命名。

    所以我们需要编辑SVG文件,使其能够满足具名元素要求。SVG图片是一种矢量图形文件格式,可以直接用代码来描绘图像,可以用任何文字处理工具打开SVG图像,通过改变部分代码来使图像具有交互功能。

    我在搜索之后找到了一个古早的软件SVGDeveloper,这个软件很难找(也很难用),上次更新还是在2014年,用的还是上个世纪的图形化界面,整体呈现一种复古感。

    但使用起来没什么问题,功能也很多,从四面八方的工具栏就可以看出来,这次我采用的就是这个编辑器。将UI设计好的png图导入,用钢笔工具不用太细致地描出各个地市的边缘,当然别忘了在path 中加入name使其成为具名元素。如下图所示:

    然后不断重复,画出每个地市的每个区县,最后需要去掉边缘线添加填充色(画图时不加填充色是避免影响视觉,最后需要添加是因为不添加的画ECharts就当这块具名元素是透明的,但SVG里的颜色和最后ECharts所展示的颜色无关,可以随意设置),最后拿到的SVG图是这样的:

    按上一步导入ECharts之后得到的效果就是这样:

    交互、倒影,所有的要求都满足了,并且用的是最简单的实现方式。

    之后我才发现SVG的在线编辑器也有很多,总体都大同小异,这里放一个吧。我所需要的功能它都有了,比起软件更加现代化,简单使用是没问题的。

    svg在线编辑器_svg矢量图在线制作工具-易点在线矢量图形编辑器

    💡 需要补充一个点:将png图片导入SVGDeveloper之后它是可以正常显示的,但做好后的图导入ECharts就只显示每个区域而不显示png背景,这是因为引入的图片地址是存储在本地的,当上传服务器后他就找不到这个文件,如下图所示。

    我的处理办法是将图片转为Base64编码,可以找到很多上传文件转Bese64编码的网站,在这里放上一个。

    测试了上面这个在线的SVG编辑器之后发现,导入图片之后它就已经自动转换成Base64编码了,省去了这一次操作步骤。

    2.OpenLayer的基础入门

    因为遇到了另一个需求,需要多地图有多种操作,ECharts的地图已经不能满足,所以后来我们选择了使用OpenLayer来制作这部分的地图。

    OL是一个很庞大的体系,但入门起来也十分简单,只需要掌握Map、View、Source、Layer这几个核心类,就可以做出一个最基本的地图,需要在此基础上添加更多花样化定制化的GIS功能到时候再按需学习也可以。

    一个大的容器Map,加上一个视角View,将来自数据源Source的图层Layer一层层叠加,就组合成了一个基本的地图。

    Map类是一个容器,接下来提到的其他类都是被包含在其中的,最重要的一个属性就是target了,target属性设置的是地图要挂载到哪个DOM节点上进行渲染。其他还有interactions 用来控制交互动作,controls 用来控制相关控件等,详细可以查看官方API文档

    View类是类似于相机,用于变化不同视角,里面一些比较常见的属性比如zoom控制缩放,extent控制视野范围,center是地图中心点等。

    Source

    Source类是指的数据源,又被分为了很多子类:OSM、ImageSource**、**TileSources、VectorSource 等,根据实际情况选择不同类型数据源进行读取,本次项目使用较多的就是VectorSource ,因为大多都是读取的一些JSON文件,以及使用turfJS绘制的矢量图像。

    Layer

    Layer类是重点,地图正是一层一层图层叠加出来的,就如下图所示,这是放大地图后默认显示的四个图层,当地图缩小之后这四个图层将不可见,同时将另外的图层设为可见,另外点击地图上的点,还会出现对应时延圈,这也是三个图层。

    将以上四个类有机结合起来,就可以组成一个完整的地图了,一个简易代码demo:

    import Map from 'ol/Map';
    import View from 'ol/View';
    import OSM from 'ol/source/OSM';
    import TileLayer from 'ol/layer/Tile';
    new Map({
      layers: [
        new TileLayer({source: new OSM()})
      view: new View({
        center: [0, 0],
        zoom: 2
      target: 'map'
    

    ECharts相关

    我就接着补充两个可能会有用的part,以防不时之需。

    1.在ECharts的tooltip中使用HTML标签

    tooltip是ECHarts一个很重要的部分,它独特的回调函数formatter属性

    formatter(params: Object|Array, ticket: string, callback: (ticket: string, html: string)) => string | **HTMLElement** | **HTMLElement[]**
    

    这是label、legend等其他配置项都不具有的功能(不用试了我已经试过一遍了),label最接近的一个解决方案是使用富文本rich,但仍有很大局限性,而在HTML标签中甚至可以再加入ECharts实现套娃 ,子子孙孙无穷尽也。

    从上面官方给出的回调函数中可以看到有params、ticket、callback三个参数,具体是什么内容可以自己打印看看。

    在函数中定义一个变量htmlStr,然后就可以在变量中书写HTML内容,写法和正常写HTML一样,标签内可以使用style参数定义样式,最后将htmlStr变量return就可以看到效果了。

    ⚠️ HTML内容需要包含在反引号 ( ` )中,而不是单、双引号中

    2.水球图相关

    水球图‣是ECharts的一个社区扩展,提供了一种适合于展现单个百分比数据的图表,支持多条水波和动画。

    水球图支持自定义的配置项很多,包括但不限于波浪条数、颜色、振幅、动画甚至外框的形状,具体配置项内容可以看这篇文章或查询官方文档

    ⚠️ **注意:echarts-liquidfill@3版本匹配echarts@5版本,echarts-liquidfill@2版本匹配echarts@4版本,并且水球图是社区扩展,所以需要单独安装引入

    一些插件分享

    很多插件是前端之光,减少了很多工作量,能使用轮子的地方就不用自己造了。

    1.vue-seamless-scroll

    vue-seamless-scroll

    一个简单的基于vue.js的无缝滚动插件,可以支持上下左右无缝滚动,单步滚动,以及支持水平方向的手动切换功能,大屏里很常用。

    ⚠️ 注意:vue-seamless-scroll 仅支持Vue2,如果想在Vue3中使用,请使用此项目Issues中其他用户扩展的Vue3兼容版vue3-seamless-scroll

    2.Swiper

    Swiper中文网-轮播图幻灯片js插件,H5页面前端开发

    一款滑动插件,效果类似于element的走马灯,不过这个插件效果更加强大,可定制化程度更高,效果也更好,同时支持电脑和移动端。

    谢谢大家🎉

  • 六年前端面试报告
  •