1. 程式人生 > >Echarts實現地圖下鑽+對應區域資料展示+右鍵返回上一級

Echarts實現地圖下鑽+對應區域資料展示+右鍵返回上一級

Echarts版本是 echarts 4

研究了三天Echarts,終於實現了基於Echarts 實現地圖下鑽至縣區,加對應區域的資料展示。先看效果圖

這裡寫圖片描述

後續更新研究的過程,建議要想使用用echarts的同學先去看官方文件和示例,不要盲目的去搞。我前一天在弄資料新增到地圖上展示,自己在瞎搞了一天,也沒搞出過所以然來。後來去看了半天文件,對著示例研究,終於把資料展示弄清楚了。接下來就是繫結資料就可以了,開心。

2018/3/26 更新

  1. 修改樣式,根據色階數值地圖塊顯示不同的顏色
  2. 按月份篩選資料,日期外掛是原生的html5 input date
  3. 每個對應區域的下一級同樣按篩選月份顯示資料
  4. 實現右鍵返回
    1. 查找了 echarts 官方api文件,滑鼠事件 myChart.on('contextmenu', ()=>{})
    2. 去掉瀏覽器預設右鍵選單 + echarts右鍵事件
let canvas = document.getElementsByTagName("body")
canvas.oncontextmenu = function(){return false;}
myCharts.on('contextmenu,function(params){
    //滑鼠右鍵事件,顯示右鍵返回上一級
    $('#context-menu').css({
        left: params.event.offsetX,
        top: params.event.offsetY
    })
})

9Oe9ds.png

  1. 右鍵返回需要用到棧來實現
    1. 點選地圖進入下一級的時候,把當前渲染好的資料入棧
    2. 右鍵返回上一級,資料出棧,重新渲染 (不知道能不能實現想瀏覽器一樣,單純的返回上一個頁面,而不需要重新渲染)

這裡寫圖片描述

修bug TODO

  • [x] 非同步載入資料,先渲染地圖,ajax拿到資料後再渲染資料
  • [x] 下鑽地圖,+ 顯示對應區域的資料
  • [x] 判斷直轄市,二級下鑽資料區分
  • [x] 修改樣式, TODO 瞭解了修改樣式的引數,可能還需要修改
  • [ ] 顯示資料的環比、同比
  • [x] 上海區域地圖缺失,莫名奇妙就修復了,應該把demo中完整的地圖檔案複製過來了
  • [ ] 地區資料百分比,百分比地圖資料關聯
  • [x] 地區資料按月份傳遞顯示,叫後臺改介面,新增傳遞年月引數,下一級介面相應的也加上引數
  • [x] 限制地圖點選事件無限入棧,設定判斷 if(mapStack < 2) {mapStack.push()}

過程中出現了兩次人為錯誤
1. 寫一個for迴圈的時候,判斷條件 漏寫(紅框),低階的語法錯誤,難怪一直提示 xxx undefined
2. 這裡寫圖片描述
3. 另一個地方也是低階的邏輯錯誤,寫錯了字母
4. 這裡寫圖片描述

新增功能
增加了圖例選擇功能,選擇不同的資料型別,展示不同的資料。
1. 一開始的思路是想在原來的地圖通通過 圖例改變事件 的api 改變地圖資料,來展示。
結果,實現邏輯太複雜,自己把自己繞暈了
2. 經前輩指導,通過按鈕連結跳轉,copy4份地圖,資料改變就可以了,get

這裡寫圖片描述
這個效果體驗不好,不要了,再修改

添加了一個模態框,點選展示對應對應地區的月份資料
這裡寫圖片描述

2018/3/27更新

實現地區資料排行條狀圖

知識點

  • 資料排序
  • 資料渲染,關聯
  • 當前資料入棧 與 出棧
  • 封裝公共的部分程式碼
  • 更新修bug表

9Xmfeg.png

果然是細節決定成敗
要養成寫程式碼註釋的習慣,不然,程式碼多的時候,上文定義的變數,下文就忘記了,容易出錯。

2018/4/17 更新

修bug TODO

2018/4/22更新bug表
* [x] 非同步載入資料,先渲染地圖,ajax拿到資料後再渲染資料
* [x] 下鑽地圖,+ 顯示對應區域的資料
* [x] 判斷直轄市,二級下鑽資料區分
* [x] 修改樣式, TODO 瞭解了修改樣式的引數,可能還需要修改
* [x] 顯示資料的環比、同比
* [ ] 上海區域地圖缺失
* [x] 地區資料百分比,百分比地圖資料關聯(引入vue資料繫結)
* [x] 地區資料
* [x] 直轄市下鑽入棧判斷,三級下鑽入棧2次,直轄市只入棧一次,,避免出現入空棧
* [x] 下一級地圖排行榜聯動
* [x] 返回上一級,排行榜地圖資料沒有入棧,無法返回
* 資料不採用入棧的方式,通過出棧的資料重新排序渲染
* [x] (限定3級入棧,不夠優化)點選排行bar圖,出現入空棧,導致出棧會有一次空棧
* bug原因出現在二級和三級的判斷區別,把 bar 圖的seriesName 改成當前的上一級的區域名字即可
* [x] 左下角的色階最大值改成拿到資料的最大值
* 排序後把最大的值拿出來,設為 colorMax
* [x] 新增圖例“客戶環比”、”銷售額“、”銷售環比“,
* [x] 新增需求,選擇地區,顯示每個地區的環比趨勢曲線圖,與平均值對比,要求可選地區,增加一條曲線
* [x] 二級下鑽又出現bug,暫時無法修復,原因是seriesName被改變了
* [x] bug別修復,把地圖的name 改為傳遞的mapname 圖例寫死,不需要legend

  • [ ] 改變思路,放棄可選多個地區增加曲線,改為:只顯示一個地區和平局曲線,用tooltip實現每個地區的月份趨勢走向
  • [x] (後端優化SQL)介面搞定後需要弄快取,查詢太慢我這邊結果出來要很久
  • [x] 改為彈框形式彈出折線圖,利用bootstrap 模態框
  • [x] 彈框無法顯示折線圖
    • [x] 沒有設定width;寬度為0,地圖無法展示,修復
  • [x] 修改模態框和地圖樣式
  • [x] 用vue繫結地區資料,實現選擇地區,渲染對應地區的曲線
    • [x] 地區已繫結,資料沒有對應展示
    • [x] 下一級地區折線展示沒有完善
  • [x] 修改折線圖按鈕圖示
  • [x] 4份地圖配置變數冗餘混亂,抽離出公共變數,放到一個配置檔案
  • [x] 返回右鍵返回上一級,折線圖的展示資料沒有對應入棧出棧繫結,會導致只能下鑽能拿資料,返回上一級資料還停留在上一次的地圖

拿資料過程出現的bug

//uncaught typeerror can read protecty 'id' of undefined
for (let i=0; res.msg.length; i++) {   
tmp2.push({
       id: res.msg[i].id,
       areaid: res.msg[i].areaid,
       name: res.msg[i].area,
       value: res.msg[i].num
   })
}

部分參考程式碼,右鍵點選地圖事件,地圖下鑽

chart.on("click", function(params) {
//隱藏右鍵返回選單
$("#contextMenu").hide();
let tmpObj = {};
let d = [];
if (params.name in provinces) {
 //二級直轄市資料渲染
 if (special.indexOf(params.name) >= 0) {
   let postData2 = {
     parentid: "provinceid",
     value: params.data.id
   };
   Promise.all([ajaxRequest(getCityNumberUrl, searchtime, postData2)]).then(
     result => {
       let [curMonthResult, lastMonthData] = result;
       let tmp = [];
       if (curMonthResult.errcode == 1) {
         getAreaNumber(
           params.name,
           curMonthResult.msg[0].cityid,
           searchtime
         );
       }
     },
     error => {
       console.log("請求市級資料失敗", e);
     }
   );
 }
 //如果點選的是34個省、市、自治區,繪製選中地區的二級地圖
 $.getJSON(provinceJson + provinces[params.name] + ".json", function(
   data
 ) {
   echarts.registerMap(params.name, data);
   for (var i = 0; i < data.features.length; i++) {
     d.push({
       name: data.features[i].properties.name
     });
   }
   renderMap(params.name, d);
   if (params.data.id !== "undifiend") {
     getCityNumber(params.name, params.data.id, searchtime, data);
   }
 });
} else {
 //顯示縣級地圖
 $.getJSON(cityJson + cityMap[params.name] + ".json", function(
   data
 ) {
   echarts.registerMap(params.name, data);
   let d = [];
   for (var i = 0; i < data.features.length; i++) {
     d.push({
       name: data.features[i].properties.name
     });
   }
   renderMap(params.name, d);
   if (params.data.cityid) {
     let postData3 = {
       parentid: "cityid",
       value: params.data.cityid
     };
     Promise.all([
       ajaxRequest(getAreaNumberUrl, searchtime, postData3)
     ]).then(
       result => {
         let [curMonthResult, lastMonthData] = result;
         let tmp = [];
         if (curMonthResult.errcode == 1) {
           // console.log('204', res.msg[0].cityid, res.msg[0].city)
           //這裡傳遞的城市名有問題“北京市”,渲染地圖的名字是“北京”,所以地圖名要用原來的名字渲染
           getAreaNumber(params.name, params.data.cityid, searchtime);
         }
       },
       error => {
         console.log("請求市級資料失敗", e);
       }
     );
   }
 });
}