如何使用 Echarts 和 SVG文件写大屏可视化地图 ?

发表于 3年以前  | 总阅读数:918 次

契机

最近公司要做一个政务大屏项目,由于在员工竞优大会上表(jing)现(chui)良(niu)好(b)的我说希望未来能做一个大屏项目,于是这个任务自然交到我头上(需求来得真快),当我拿到图的时候发现地图上有定制化的元素,就是下面图中的三条河流

如果想要使用 GeoJSON 的方式,那就必须知道三条河流的坐标系才行,可是 UI 小姐姐说需求方给的河流就是个图层,她只贴到地图上而已,并没有坐标方面的数据。

我需要根据 SVG将地图渲染出来。并添加一些额外的元素。

于是便有了这篇文章。

纯当是一次实践记录。

选择正确的地图组件

原先我们的地图则只能使用 GeoJSON 格式来作为底图进行描绘,Echarts 从最新的第5版本开始支持地理坐标系(geo)和地图系列(map series)中使用 SVG 作为底图。

  • 地理坐标系(geo)[1] :地理坐标系组件。地理坐标系组件用于地图的绘制,支持在地理坐标系上绘制散点图[2],线集[3]。
  • 地图系列(map series)[4] :地图,主要用于地理区域数据的可视化,配合 visualMap[5] 组件用于展示不同区域的人口分布密度等数据。

地理坐标系跟地图系列的最大不同可能就是绘制散点图、线集的,这点在官方网站上是有写的

如果要实现点数据或者线数据的可视化,可以使用在地理坐标系组件[6]上的散点图[7]和线图[8]。

当然,我们学习 Echarts 不可能干啃API,自然需要结合生动的例子,这里就用官方的示例庖丁解牛[9]和散点图[10]来作为两者的区别所在,通过官方的配置项我们可以看到配置是不同的

        series: [{
            name: 'French Beef Cuts',//庖丁解牛配的是地图系列
            type: 'map',
            map: 'Beef_cuts_France',
            ...
        }]
        geo: {
            tooltip: {
                show: true
            },
            map: 'iceland_svg',//散点图配的是地图坐标系
           ...
        },

视觉上的不同自然就是散点了,散点长这样

由于我们的项目需要加很多散点,所以我们自然要选择geo组件。

具名元素

什么是具名元素呢?就是有名字的 SVG 元素。

如果我们希望跟 SVG 元素做交互,则需要先标记这些元素,标记非常简单,就是给它加一个 name 属性。比如我们拿到 SVG 文件后,可以在 path 上加上名称属性name="named_rect",那么这个 path 就是具名元素。

加了名字的元素跟没有名字的元素有非常大的区别,一旦加上名字,就可以拥有高亮、淡入淡出、文字标注、提示框等交互功能,作为例子,以下放官方给的例子

<svg xmlns="http://www.w3.org/2000/svg" version="1.2" fill-rule="evenodd" xml:space="preserve">
    <path name="named_rect" d="M 0,0 L 0,100 100,100 100,0 Z" fill="#765" />
    <path d="M 150,0 L 150,100 250,100 250,0 Z" fill="#567" />
</svg>

左边的矩形由于加了 name,就自动拥有 hover 时高亮的效果,而右边的则没有。

而且加了 name 后的具名元素还可以在 Echarts 的 options 中配置geo.regions[11]以做特定的配置效果,这个配置效果会跟我们起的 name 做匹配。

option = {
    geo: {
        map: 'some_svg',
        regions: [{
            name: 'element_name_1',//这里跟 svg 源文件中的 name做匹配
            itemStyle: { ... }
        }, 
    }
};

注意:

  • 只有这些 SVG 元素可以被命名: rectcirclelineellipsepolygonpolylinepathtexttspang
  • 支持多个元素以相同的名称命名,这样它们能被同时高亮、选中。

实战开始吧!

下面我将使用slice[12]作为底图,这个文件是UI 小姐姐通过 figma 导出来给到我的。

我们的目标是使用此文件配合 Echarts 在浏览器上描绘地图,并做一些简单的交互效果来熟悉 Echarts 的配置项。

给 path 加上具名元素

拿到SVG文件后,我们需要使用 Chrome打开它, 使用 vscode 打开后的 SVG 是一串 XML 标签,而 Chrome 打开后会自动解析(就跟解析 HTML一样),并且渲染出效果来。

每个 SVG矢量文件本质上是很多定义好的线和形状来创建的图形,里面最常用的可能是 path 路径标签,而且它是最强大的一个,可以通过它创建各种线条、曲线、弧形等等。

我们在浏览器中打开F12开发者工具,并且选择小箭头对准渲染出来的图片,就可以看到某块区域的 path

现在已经很清楚了,整块底图都是用大量的 path 进行描绘的,而 path 的形状是通过属性 d 来定义的。

我们不关心 d 属性是怎样写出来的,现在要做的,就是在 SVG 源文件中给对应的path 加上 name 属性。

<path name="昭通市"  d="M480.832 ..."

基本用法

接着我们需要在框架中使用Echarts 了,这里选用 React作为 UI 框架,这里是基本结构

import React, { useEffect } from 'react';
import * as echarts from 'echarts';
import jQuery from 'jquery';
window.$ = jQuery;

export const Middle = () => {
  //创建 map 的函数,在里面写 Echarts 的配置项
  const createMap = id => {};
  useEffect(() => {
    createMap('map');
  }, []);
  return <div id='map' />;
};

接着我们在createMap这个函数中使用 Echarts,这里是SVG 作为底图的写法

  const createMap = id => {
    const myChart = echarts.init(document.getElementById(id)!);
    //$.get()里写你的SVG 文件路径
    $.get('/slice.svg', function (svg) {
      //首先向 echarts 注册 SVG 字符串或解析过的 SVG DOM
      echarts.registerMap('map', { svg: svg });
      var option = {
        toolTip: {},
        //开启地理坐标系组件。地理坐标系组件用于地图的绘制,支持在地理坐标系上绘制散点图,线集。
        geo: {
          map: 'map', //这里写注册过的map 名字
        },
      };
      myChart.setOption(option);
    });
  };

现在打开浏览看可以查看到效果了,不出意外的话,你可以看到这样的效果

由于我只给一个path 添加name,所以只有这一个元素会移动时高亮。

给地图加上文字

上面的效果是 hover 时拥有文字效果,这里有两种方式可以加文字

  • SVG 源文件中加 text 标签
  • Echarts 中配置

SVG 源文件中加就比较基础了,需要我们写 xml 标签,比如这样

<text xml:space="preserve" style="font-size:14px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:center;text-anchor:middle;fill:rgba(61,215,255,55%);fill-opacity:1;stroke:none;font-family:DejaVu Sans;-inkscape-font-specification:Bitstream Vera Sans Bold" x="128.21919" y="112.48651" id="text3831" transform="matrix(0.99999776,-0.00211681,0.00211681,0.99999776,0,0)">
<tspan sodipodi:role="line" x="550.59958" y="160.12965" id="tspan38351">
昭通市</tspan>
</text>

这是我在SVG 源文件里面写的,缺点是要找 x 点和 y 点,然后写在对应的 x 属性和 y 属性中。

更简单的方法是直接用 Echarts 的配置项option.geo 自动加上标注文字。

        geo: {
          map: 'map', //这里写注册过的map 名字
          //文字标注的配置
          label: {
            show: true,//显示
            color: 'rgba(61, 215, 255, 0.55)',//颜色
          },
        },

我在这里选择的方式是在源文件中写 text 标签,因为需要还原设计稿,统一的配置无法满足我的要求,具体看需求就行。

我加好 name 跟 text 的文件在这:map[13]

高亮强调emphasis

默认的高亮无法满足我们的要求,所以我们可以通过emphasis来配置高亮的效果

        geo: {
         ...
          emphasis: {
            focus: 'none', //高亮时聚焦自己
            itemStyle: {
              areaColor: '#2080D7',
              borderColor: '#2B91B7', //地图区域的颜色。
              borderWidth: 2,
              opacity: 1,
              shadowColor: 'rgba(74, 188, 251, 0.4)',
              shadowBlur: 3,
              shadowOffsetX: 3,
              shadowOffsetY: 3,
            },
            label: {
              show: false, //高亮时文字不要出现
            },
          },
        },

具体配置都是查的官方文档,geo.emphasis[14]

现在的效果是这样的

Sep-19-2021 12-00-25.gif

地域分块regions自定义样式

如果想要统一设置样式,可以使用 geo.itemStyle配置

          //统一样式配置
          itemStyle: {
            areaColor: '#1C3079',
            borderColor: '#2ab8ff',
          },

如果需要分块定制配置,就需要使用geo.regions这个配置项。

            //单独定制的区块设置
            regions: [
              {
                name: '昭通市',
                itemStyle: {
                  areaColor: 'rgba(44, 76, 187, 1)',
                },
              },
              {
                name: '玉溪市',
                itemStyle: {
                  areaColor: 'rgba(44, 76, 187, 1)',
                },
              },
              {
                name: '怒江傈傈族自治州',
                itemStyle: {
                  areaColor: 'rgba(44, 76, 187, 1)',
                },
              },
              {
                name: '迪庆藏族自治区',
                itemStyle: {
                  areaColor: 'rgba(44, 76, 187, 1)',
                },
              },
              {
                name: '楚雄彝族自治州',
                itemStyle: {
                  areaColor: 'rgba(16, 34, 84, 1)',
                },
              },
              {
                name: '红河哈尼族彝族自治州',
                itemStyle: {
                  areaColor: 'rgba(16, 34, 84, 1)',
                },
              },
              {
                name: '丽江市',
                itemStyle: {
                  areaColor: 'rgba(16, 34, 84, 1)',
                },
              },
            ],

目前我们分别有geo.regions.itemStyle、geo.itemStyle、geo.emphasis.itemStyle,他们分别可以定制化地区的样式、全局统一样式和高亮时的样式,API 颗粒度的划分非常精细,只需要到对应的父级配置项查询即可。

image-20210919121750115.png

layout布局

如果希望整个地图能够尽量占满我们设定好的div 的宽高,就需要在 geo 中配置以下内容,以填充Echarts 容器。

  layoutSize: '100%', //布局尺寸
  layoutCenter: ['50%', '50%'], //布局位置

series系列

series 是 Echarts 中最重要的属性,几乎配置任何图表都离不开它,通过 series 的 type 属性,我们可以定制诸如折线 line、柱状图 bar、饼图 pie、散点气泡图scatter等等特效效果。

我的项目中需要使用到series-effectScatter(带有涟漪效果的散点图)和series-scatter(散点气泡图),具体 API 可以通过option[15]查看,这里我就直接贴代码

    const mapData = [
      {
        name: '古水水电站1',//数据名称,对应 option.tooltip.formatter
        value: [190, 215],//坐标
      },
      {
        name: '红色水电站8',
        value: [366, 260],
      },
      {
        name: '红色水电站9',
        value: [436, 270],
      },
      {
        name: '红色水电站10',
        value: [470, 500],
      },
      {
        name: '红色水电站11',
        value: [520, 310],
      },
    ];
      var option = {
        //全局开启提示框的样式配置,这里如果配置,有几率下面所有散点图不会出现提示框。
        tooltip: {
          show: true,//开启全局提示框
          formatter: '{b}',//格式化,选择显示数据名称
          backgroundColor: 'rgba(7, 26, 55, 0.8)',
          borderColor: '#3DD7FF',
          borderWidth: 1,
          padding: [3, 5, 3, 5],
          textStyle: {
            color: 'white',
          },
        },
        ...
        series: [
          {
            //带有涟漪特效动画的散点(气泡)图
            type: 'effectScatter',
            coordinateSystem: 'geo', //该系列使用的坐标系
            tooltip: {
              show: false,//这个系列不要提示框
            },
            //涟漪特效相关配置。
            rippleEffect: {
              brushType: 'stroke', //波纹的绘制方式 一笔一笔
              scale: 4,
            },
            showEffectOn: 'render', //绘制完成后显示特效 'emphasis' 高亮(hover)的时候显示特效
            symbol: 'circle', //涟漪特效的标记图形
            symbolSize: [8, 5], //图形尺寸 宽 高
            zlevel: 1, //优先级
            //图形样式
            itemStyle: {
              color: 'yellow',
            },
            //系列中的数据内容数组。数组项通常为具体的数据项。
            data: mapData.map(item => item.value),
          },
          {
            //系列类型 散点(气泡)图。
            type: 'scatter',
            coordinateSystem: 'geo',
            tooltip: {
              show: true,//这个系列要提示框
            },
            symbol: 'pin',
            emphasis: {
              scale: true,
            },
            symbolSize: [30, 33],
            symbolOffset: [0, -5],
            zlevel: 20,
            itemStyle: {
              color: 'red',
            },
            data: mapData,
          },
        ],
      };

这样效果就大概有了

获取坐标轴

上面的 mapData 中的 value,在这个项目中表示坐标轴(具体看 data 的配置,也可以是数据),但是我们并不知道坐标轴是多少,如果挨个试太浪费时间,还好 Echarts 提供给我们 API,我们可以通过监听事件来获取坐标

 //获取 svg 底图的坐标
    myChart.getZr().on('click', function (params) {
      var pixelPoint = [params.offsetX, params.offsetY];
      var dataPoint = myChart.convertFromPixel({ geoIndex: 0 }, pixelPoint);
      // 在 SVG 上点击时,坐标会被打印。
      // 这些坐标可以在 `series.data` 里使用。
      console.log(dataPoint);
    });

事件

如果要对 SVG 元素进行操作,可以指定事件

// 'name1' 是一个 SVG 元素的名字。
myChart.on('click', { geoIndex: 0, name: 'name1' }, function (params) {
    console.log(params);
});

如果想要对series 中诸如 type 为 scatter 的散点图绑定点击事件,则可以这样写

myChart.on('click', 'series.scatter', function (params: any) {
     console.log(params);
});

每个项目都少不了自适应,如果想要 Echarts 的地图自适应,则需要监听 window 的 resize 事件,然后调用 Echarts 实例的 resize 方法

window.addEventListener('resize', () => {
     myChart?.resize();
});

目前我的项目只需要用到这三个事件API,还有更多定制化的事件,可按需查文档echarts-event[16]

结束语

以上的记录只是项目的一个基本结构,不代表最终项目品质。基于上面的结构,我们已经能够在 SVG 地图上做出非常多样的样式效果和定制服务了。

如果觉得自己配置比较麻烦的话,可以参考这个网站makeapie[17],找别人写好的案例,copy一下配置项即可。

本文由哈喽比特于3年以前收录,如有侵权请联系我们。
文章来源:https://mp.weixin.qq.com/s/nGUy18oR8q3Q7zPP_F2yYw

 相关推荐

刘强东夫妇:“移民美国”传言被驳斥

京东创始人刘强东和其妻子章泽天最近成为了互联网舆论关注的焦点。有关他们“移民美国”和在美国购买豪宅的传言在互联网上广泛传播。然而,京东官方通过微博发言人发布的消息澄清了这些传言,称这些言论纯属虚假信息和蓄意捏造。

发布于:1年以前  |  808次阅读  |  详细内容 »

博主曝三大运营商,将集体采购百万台华为Mate60系列

日前,据博主“@超能数码君老周”爆料,国内三大运营商中国移动、中国电信和中国联通预计将集体采购百万台规模的华为Mate60系列手机。

发布于:1年以前  |  770次阅读  |  详细内容 »

ASML CEO警告:出口管制不是可行做法,不要“逼迫中国大陆创新”

据报道,荷兰半导体设备公司ASML正看到美国对华遏制政策的负面影响。阿斯麦(ASML)CEO彼得·温宁克在一档电视节目中分享了他对中国大陆问题以及该公司面临的出口管制和保护主义的看法。彼得曾在多个场合表达了他对出口管制以及中荷经济关系的担忧。

发布于:1年以前  |  756次阅读  |  详细内容 »

抖音中长视频App青桃更名抖音精选,字节再发力对抗B站

今年早些时候,抖音悄然上线了一款名为“青桃”的 App,Slogan 为“看见你的热爱”,根据应用介绍可知,“青桃”是一个属于年轻人的兴趣知识视频平台,由抖音官方出品的中长视频关联版本,整体风格有些类似B站。

发布于:1年以前  |  648次阅读  |  详细内容 »

威马CDO:中国每百户家庭仅17户有车

日前,威马汽车首席数据官梅松林转发了一份“世界各国地区拥车率排行榜”,同时,他发文表示:中国汽车普及率低于非洲国家尼日利亚,每百户家庭仅17户有车。意大利世界排名第一,每十户中九户有车。

发布于:1年以前  |  589次阅读  |  详细内容 »

研究发现维生素 C 等抗氧化剂会刺激癌症生长和转移

近日,一项新的研究发现,维生素 C 和 E 等抗氧化剂会激活一种机制,刺激癌症肿瘤中新血管的生长,帮助它们生长和扩散。

发布于:1年以前  |  449次阅读  |  详细内容 »

苹果据称正引入3D打印技术,用以生产智能手表的钢质底盘

据媒体援引消息人士报道,苹果公司正在测试使用3D打印技术来生产其智能手表的钢质底盘。消息传出后,3D系统一度大涨超10%,不过截至周三收盘,该股涨幅回落至2%以内。

发布于:1年以前  |  446次阅读  |  详细内容 »

千万级抖音网红秀才账号被封禁

9月2日,坐拥千万粉丝的网红主播“秀才”账号被封禁,在社交媒体平台上引发热议。平台相关负责人表示,“秀才”账号违反平台相关规定,已封禁。据知情人士透露,秀才近期被举报存在违法行为,这可能是他被封禁的部分原因。据悉,“秀才”年龄39岁,是安徽省亳州市蒙城县人,抖音网红,粉丝数量超1200万。他曾被称为“中老年...

发布于:1年以前  |  445次阅读  |  详细内容 »

亚马逊股东起诉公司和贝索斯,称其在购买卫星发射服务时忽视了 SpaceX

9月3日消息,亚马逊的一些股东,包括持有该公司股票的一家养老基金,日前对亚马逊、其创始人贝索斯和其董事会提起诉讼,指控他们在为 Project Kuiper 卫星星座项目购买发射服务时“违反了信义义务”。

发布于:1年以前  |  444次阅读  |  详细内容 »

苹果上线AppsbyApple网站,以推广自家应用程序

据消息,为推广自家应用,苹果现推出了一个名为“Apps by Apple”的网站,展示了苹果为旗下产品(如 iPhone、iPad、Apple Watch、Mac 和 Apple TV)开发的各种应用程序。

发布于:1年以前  |  442次阅读  |  详细内容 »

特斯拉美国降价引发投资者不满:“这是短期麻醉剂”

特斯拉本周在美国大幅下调Model S和X售价,引发了该公司一些最坚定支持者的不满。知名特斯拉多头、未来基金(Future Fund)管理合伙人加里·布莱克发帖称,降价是一种“短期麻醉剂”,会让潜在客户等待进一步降价。

发布于:1年以前  |  441次阅读  |  详细内容 »

光刻机巨头阿斯麦:拿到许可,继续对华出口

据外媒9月2日报道,荷兰半导体设备制造商阿斯麦称,尽管荷兰政府颁布的半导体设备出口管制新规9月正式生效,但该公司已获得在2023年底以前向中国运送受限制芯片制造机器的许可。

发布于:1年以前  |  437次阅读  |  详细内容 »

马斯克与库克首次隔空合作:为苹果提供卫星服务

近日,根据美国证券交易委员会的文件显示,苹果卫星服务提供商 Globalstar 近期向马斯克旗下的 SpaceX 支付 6400 万美元(约 4.65 亿元人民币)。用于在 2023-2025 年期间,发射卫星,进一步扩展苹果 iPhone 系列的 SOS 卫星服务。

发布于:1年以前  |  430次阅读  |  详细内容 »

𝕏(推特)调整隐私政策,可拿用户发布的信息训练 AI 模型

据报道,马斯克旗下社交平台𝕏(推特)日前调整了隐私政策,允许 𝕏 使用用户发布的信息来训练其人工智能(AI)模型。新的隐私政策将于 9 月 29 日生效。新政策规定,𝕏可能会使用所收集到的平台信息和公开可用的信息,来帮助训练 𝕏 的机器学习或人工智能模型。

发布于:1年以前  |  428次阅读  |  详细内容 »

荣耀CEO谈华为手机回归:替老同事们高兴,对行业也是好事

9月2日,荣耀CEO赵明在采访中谈及华为手机回归时表示,替老同事们高兴,觉得手机行业,由于华为的回归,让竞争充满了更多的可能性和更多的魅力,对行业来说也是件好事。

发布于:1年以前  |  423次阅读  |  详细内容 »

AI操控无人机能力超越人类冠军

《自然》30日发表的一篇论文报道了一个名为Swift的人工智能(AI)系统,该系统驾驶无人机的能力可在真实世界中一对一冠军赛里战胜人类对手。

发布于:1年以前  |  423次阅读  |  详细内容 »

AI生成的蘑菇科普书存在可致命错误

近日,非营利组织纽约真菌学会(NYMS)发出警告,表示亚马逊为代表的电商平台上,充斥着各种AI生成的蘑菇觅食科普书籍,其中存在诸多错误。

发布于:1年以前  |  420次阅读  |  详细内容 »

社交媒体平台𝕏计划收集用户生物识别数据与工作教育经历

社交媒体平台𝕏(原推特)新隐私政策提到:“在您同意的情况下,我们可能出于安全、安保和身份识别目的收集和使用您的生物识别信息。”

发布于:1年以前  |  411次阅读  |  详细内容 »

国产扫地机器人热销欧洲,国产割草机器人抢占欧洲草坪

2023年德国柏林消费电子展上,各大企业都带来了最新的理念和产品,而高端化、本土化的中国产品正在不断吸引欧洲等国际市场的目光。

发布于:1年以前  |  406次阅读  |  详细内容 »

罗永浩吐槽iPhone15和14不会有区别,除了序列号变了

罗永浩日前在直播中吐槽苹果即将推出的 iPhone 新品,具体内容为:“以我对我‘子公司’的了解,我认为 iPhone 15 跟 iPhone 14 不会有什么区别的,除了序(列)号变了,这个‘不要脸’的东西,这个‘臭厨子’。

发布于:1年以前  |  398次阅读  |  详细内容 »
 相关文章
Android插件化方案 5年以前  |  237231次阅读
vscode超好用的代码书签插件Bookmarks 2年以前  |  8065次阅读
 目录