如何在微信小程式中使用Echarts
前言:
之前因為疫情,看到有許多做疫情動態的小程式,自己也跟著做了一個
總的來說,不難,就是有介面,拿到資料之後,就進行展現就好
不過其中比較難的,就是疫情地圖部分,使用的是Echarts的視覺化地圖
先上張圖,這裡只講這個map元件(資料滯後,不要當真)
我使用的時候遇到很多坑,而且看文件和部落格,對在小程式中使用Echarts的一些介紹比較少
所以我做出來了,就想詳細寫一寫
不過因為有事一直耽擱了,過得時間有點長了,我主要是想說一些需要注意的點,具體完整程式碼可看我github連線
正文:
首先,建議還是自己上官網看看Echarts
其實基本的使用就已經交代清楚了,可以自己先嚐試
對於第一次使用的小白,我建議的步驟就是:
1. 先在下載 GitHub 上的ecomfe/echarts-for-weixin專案
2. 找到你想用的圖表,看它提供的程式碼,大概知道怎麼使用的
3. 將示例中的ec-canvas資料夾拷貝到你的小程式專案中的components資料夾下
4. 它提供的示例是每個圖表是一個page,但是顯然我們自己實際開發是作為一個component,所以新建一個component,靈活拷貝你想做的圖表的相關內容即可
以上沒有任何技術含量,CV解決,對於初次使用,這樣簡單粗暴的方式,至少能保證你的引入是沒有問題的,而且也好排除錯在哪
如果看到圖表正常顯示,恭喜你會使用Echarts了,是恭喜你完成了第一步
之後就是根據我們自己的需求,進行修改了。
更具體的修改使用,我將以我做的疫情地圖為例,用的是map這一元件
我先介紹幾個的主體部分,然後介紹修改
首先,在index.json的useingComponents中引入ec-canvas元件
"usingComponents": { "ec-canvas": "../../ec-canvas/ec-canvas" }
其次,在index.wxml中使用元件
<view class="mapWrap" hidden="{{isLoadingMap}}"> <ec-canvas id="mychart-dom-area"canvas-id="mychart-area" ec="{{ ec }}" class="map" bindlongpress='saveImg'></ec-canvas> </view>
- id是為了js中獲取到該例項使用的,命名不一定,規範即可
- class是為了樣式設定使用的,一般是在wxss中設定圖表的寬高
- bindlongpress就是長按事件,我這裡做的就是長按地圖儲存該地圖圖片,後會詳述
至於ec,就是關鍵了
如果你拷貝時沒有出錯,可以看到元件中的data中有個屬性,ec
它的值是一個配置物件,其中有一個配置為初始化圖表的,onInit為鍵,配置物件的鍵名是不能修改;initChart為值,是我們要定義的初始化函式。
ec: {
onInit: initChart
}
ec將傳會給ec-canvas元件,根據其不同的配置進行不同的處理,具體可看原始碼
總之在這裡傳initChart函式,就是會在元件created生命週期進行初始化圖表
我們要根據自己需求展現圖表,最主要的就是在修改initChart這個函數了
如果只是靜態資料,就按下面的寫法即可
function initChart(canvas, width, height, dpr) { // 1.固定寫法不用管 const chart = echarts.init(canvas, null, { width: width, height: height, devicePixelRatio: dpr // new }); canvas.setChart(chart); // 2.註冊地圖 echarts.registerMap('henan', geoJson); // 3.設定option const option = {...} chart.setOption(option); // 4. 返回echarts return chart; }
主要修改的就是步驟2和3
修改步驟2:
我做的是中國疫情地圖,所以需要引入的是中國地圖,是一個js檔案,是對各個省份的一些配置資訊。
從網上看到別的博主提供的檔案,連結下載,放入你的小程式元件資料夾下,可以不修改,import引入,然後修改步驟二
import geoJson from './china' // 註冊地圖 echarts.registerMap('china',geoJson)
修改步驟3:
其實挺關鍵的,這是圖表的一個配置項,配置你所希望展現的一切
但是內容太多了,例如有配置 tooltip(提示框元件)、visualMap(視覺對映元件)、toolbox(工具欄)、series(系列列表)... ...
這裡就不詳述了,文件很多也很全的。用過Echarts的很快就會用了,就算沒用過的,對著文件耐心改改就知道了,
不過還是有一些需要注意的
series中
type: 'map', //型別是地圖,用於地理資料視覺化
mapType: 'china', //註冊的地圖
data //資料來源
其中的data,若是靜態資料,寫好引入就好了,到這裡基本一箇中國疫情地圖就做完了。
但是通常情況下,data都是動態的,我們基本上都是傳送請求獲取到的
所以上面的寫法就帶來了一個問題:前面講到intiChart會在created就觸發了,如果是非同步獲取資料,往往initChart呼叫後,其中setOption中的data還沒有獲取到
這就會只顯示了個地圖,但是地圖沒有資料,同時也會報錯
所以我們要考慮的就是非同步載入元件,當時在網上沒看到相關參考後,我就去看了原始碼,自己琢磨了
但是後來發現,它提供的示例中就有非同步載入的示例,看著示例很快就知道怎麼改了
這就給我一個教訓,一定要好好看它的示例,不過吧,雖然花了不少時間,但是看了原始碼是更好理解它為什麼這麼用了
廢話說太多了,接下來講講我是怎麼使用非同步元件的
首先,關鍵在ec,不再是配置onInit了,而是設定lazyload為true,這就可以非同步載入元件了,之後可以動態進行初始化
ec: { // 將lazyLoad設為true後,就可手動初始化了 lazyLoad:true }
定義 初始化Echart的函式,之前我們在component外部定義的,這會可以把其放在methods中,可訪問到this
和上面的initChart差不多,為以下5步
initChart(){ // 1.首先獲取元件,可在父元件裡呼叫 this.selectComponent ,獲取子元件的例項物件。 const ecComponent = this.selectComponent('#mychart-dom-area'); ecComponent.init((canvas, width, height, dpr) =>{ // 2.這個不用管,固定寫法 const chart = echarts.init(canvas, null, { width:width, height:height, devicePixelRatio: dpr // new }); canvas.setChart(chart); // 3.註冊地圖 echarts.registerMap('china',geoJson) // 4.設定option this.setOption(chart); // 5.最後一定要返回chart return chart; }) },
區別在於多了第1步,和第4步中data不再是靜態資源了,而是需要向後臺獲取的:
第1步,通過之前定義的id,獲取到該echart元件例項,通過呼叫該例項的init方法初始化
第4步是我另外定義的一個函式呼叫,主要是為看著更清楚些,不想在initChart這個函式中寫太多,主要為
setOption(chart){ // 1.provinceData是父元件從後臺獲取,然後傳給這個map元件中的 // 要進行一些處理,name和china.js中對應,value就是要呈現的值,這裡就是當前確診人數 const data = this.data.provinceData.map((item,index) => { return { name:item.provinceShortName, value:item.currentConfirmedCount } }) // 2.地圖內容配置 const option = { // 提示框元件 tooltip: {...}, // 視覺對映元件 visualMap: {...}, // 工具欄 toolbox: {...}, // 系列列表。每個系列通過 type 決定自己的圖表型別 series: [{ top:0, type: 'map', //型別是地圖,用於地理資料視覺化 mapType: 'china', //註冊的地圖 // 標籤(標籤位置在china.js檔案中的properties中的cp修改) label: {...}, itemStyle: {...}, animation: false, data }], };
// 呼叫函式傳入的chart的setOption方法,將該option設定 chart.setOption(option); },
option中的一些配置項為...,是我省略沒貼上上,完整的看我的github上都有
接下來就是要在合適的時機呼叫initChart 方法就可
在這裡是父元件非同步獲取資料後,傳給map元件的,所以合適的時機就在map元件獲取到provinceData後
所以就在map的屬性列表properties中,該provinceData配置一個observer,開啟監聽,當獲取到資料的時候就呼叫initChart函式
properties: { provinceData:{ type:Array, observer(news){ if(news.length){ this.initChart() } } } },
這就完成了中國疫情地圖啦~
除此之外,還可自己多多拓展功能啊
我這裡就拓展了個,長按儲存圖片功能,就是前面說的 bindlongpress 事件
saveImg(){ wx.showModal({ title: '儲存地圖到相簿', content:"確認儲存", confirmText:'儲存', success:(res)=>{ if (res.confirm) { const ecComponent = this.selectComponent('#mychart-dom-bar'); // 先儲存圖片到臨時的本地檔案,然後存入系統相簿 ecComponent.canvasToTempFilePath({ success: res => { console.log("tempFilePath:", res.tempFilePath) // 存入系統相簿 wx.saveImageToPhotosAlbum({ filePath: res.tempFilePath || '', success: res => { console.log("success", res) }, fail: res => { console.log("fail", res) } }) }, fail: res => console.log(res) }) } } }) } },