基于Vue-Echarts实现地图渐热效果

简介


基于Element-ui, Vue和Vue-echarts的地图渐热效果实现。

效果展示地址https://dqinyuan.github.io/mapvisual/index.html (因为是托管在github上的页面,国内访问速度可能会比较慢,请耐心等待)

展示的内容是从1994年至2018年大陆金融业和房地产行业的发展情况(当地的相关企业越多则热度越大),数据全部是从猎聘网上爬取的。

数据都是按照时间从远到近有序放置的,只有这样程序才能正确地工作。

项目Github地址


https://github.com/DQinYuan/mapvisual

将项目clone下来,直接用浏览器打开/docs/index.html,也可以看到效果。

打开页面后点击左上角如下样式的圆形按钮后地图就会开始随着时间进度条渐热:

开始

一些可以修改的配置


在/src/config.js中有一些可以修改的配置,主要是和时间进度条相关的配置:

let config = {
    start:1994,     //进度条从1994年开始
    end:2018,       //进度条到2018年结束
    interval:2,     //进度条每隔2年推进一次
    time:150        //图像每150毫秒刷新一次
}
export default config;

按照这样配置出来的时间进度条会像这样:

时间进度条

注意,这个配置不仅会影响进度条的展示,程序的逻辑也会自动适应配置。我给的数据中的企业最早是1980年创立的,最晚是在2018年,如果像上面那样配置时间段位1994-2018年的话,则1980年-1994年之间创立的企业所在的地点在按钮刚点下去的时候就会是“热”的。

有关地图的样式的echarts配置在/src/components/StateGraph.vue文件中,可以参照echarts文档自行修改。

其他实现细节


最关键的三个组件是/src/App.vue,/src/Graphs.vue,/src/components/StateGraph.vue。其中StateGraph.vue组件就代表着一张echarts地图,他们包含关系如下:

组件关系

时间进度条和开始按钮等小的组件就直接放在App.vue中了,然后它包含一个Graphts.vue的组件,顾名思义,Graphs.vue就是用来放地图的,它里面包含两个StateGraph.vue组件,分别用来展示房地产行业的渐热效果与金融业的渐热效果。

代码利用Vue的数据与模块绑定的特点,直接通过往vue-echarts组件的数据数组里添加元素来实现视图的更新。

我们来追踪一下点击开始按钮之后的流程你大概就知道程序时怎么运作的了。

  • 当你点击下开始按钮的时候,App.vue的第43行处的代码会被执行:
    refreshMap(){
      //console.log("开始refresh");
      this.activeStep = 1;
      bus.$emit("refresh_map");
    }

​ 可以看到,它把进度条置于开始位置后,像总线发射了一个"refresh_map"事件。

  • Graphs.vue的第96行的如下代码监听了总线上的"refresh_map"事件:
    bus.$on("refresh_map", function() {
      clearInterval(that.timerId);
      for (let i = 0; i < that.cursors.length; i++) {
        that.cursors[i] = 0;
      }
      that.financedatas.splice(0, that.financedatas.length);
      that.estatedatas.splice(0, that.estatedatas.length);

      that.start_date = new Date(config.start, 0, 1, 0, 0, 0, 0);
      that.timerId = setInterval(that.job, config.time);
    });

这里的financedatas和estatedatas就是分别绑定金融业地图和房地产业地图视图的数组,往这两个数组里放置或者删除数据会导致地图视图的热力发生改变。这里直接使用splice方法将两个数组清空,这样地图就重新变成空的地图了,在setInterval之前的代码都是一些简单的清空操作,setInterval设置了一个定时器每隔config.time的时间执行一次job,job的内容其实就是往financedatas和estatedatas添加一些数据而已,下面具体看一看。

  • Graphs.vue的第68行代码就是job的具体内容:

        this.job = function() {
          update(finances, that.financedatas, 0, that.start_date, 10);
          update(estates, that.estatedatas, 1, that.start_date, 10);
    
          //更新时间与修改进度条
          let previousYear = that.start_date.getFullYear();
          that.start_date = utils.upgradeDateByQuarter(that.start_date);
          //console.log(previousYear);
          //console.log(that.start_date.getFullYear());
          //console.log("--------------------------------");
          // console.log(that.start_date.getMonth());
          if (previousYear != that.start_date.getFullYear()) {
            inter_flag += 1;
            if (inter_flag % config.interval == 0) {
              bus.$emit("step");
            }
            if (previousYear == config.end - 1) {
              //console.log("时间到++++++++++++++++++++++++++++=");
              clearInterval(that.timerId);
            }
          }
        };
    

    代码that.start_date = utils.upgradeDateByQuarter(that.start_date);会以季度(Quarter)为单位更新时间,如果if (previousYear != that.start_date.getFullYear())发现年份出现变化,则可能需要更新进度条,通过if (inter_flag % config.interval == 0)发现需要更新进度条之后,则向总线发送"step"事件,App.vue中监听了这个时间,就会把进度条往前推一格,这个方法的重点是最前面两行的update方法调用,update的内容其实大概就是把finances和estates(这两个代表的是全量数据)中时间点要小于that.start_date的数据加入financedatas和estatedatas,以促使视图更新。

  • update方法的内容位于Graphs.vue的第50行:

        /**
         * fields:与echarts视图绑定的数组
         * field_datas:完整的数据数组
         * cursor_index:该地图的游标在游标数组(cursors)中的位置
         * com_date:当前时间
         * factor:期望更新的点在地图中占的比重,比重越大,则越热
         */
        function update(fields, field_datas, cursor_index, com_date, factor) {
          for (
            ;
            that.cursors[cursor_index] < fields.length;
            that.cursors[cursor_index]++
          ) {
            let field = fields[that.cursors[cursor_index]];
            // console.log(utils.date2string(this.start_date));
            // console.log(finance.datestr);
            if (utils.string2date(field.datestr).valueOf() <= com_date.valueOf()) {
              field_datas.push([field.lon, field.lat, factor]);
            } else {
              break;
            }
          }
        }
    

    就是一个for循环,if (utils.string2date(field.datestr).valueOf() <= com_date.valueOf())发现全量数据(field_datas)中有小于当前时间点的,就通过push方法将其加入与视图绑定的数组中,促使视图更新。

END


最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,185评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,445评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,684评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,564评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,681评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,874评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,025评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,761评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,217评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,545评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,694评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,351评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,988评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,778评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,007评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,427评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,580评论 2 349

推荐阅读更多精彩内容