小程序使用echarts 在一個頁面打印多個餅圖的坑

1、下載echarts微信版

下載地址:https://github.com/ecomfe/echarts-for-weixin
或者直接雲盤下載 https://pan.baidu.com/s/1iOXILEZlmGYzzSin_TK22A 提取碼 fwhxcss

2、建立所需文件

同時將下載的echarts 文件拷入,目錄以下
在這裏插入圖片描述html

3、建立一個配置option 的js

echart-option-config.js 配置option相關數據

var getOption = function (title,seriesName, dataArray) {
  var option = {
    title: {
      text: title ||'數據來源',
      x: 'left',
      textStyle:{
        fontSize:36
      }
    },
    tooltip: {
      trigger: 'item',
      formatter: "{a} <br/>{b}: {c} ({d}%)"
    },
    series: [
      {
        name: seriesName || '訪問來源',
        type: 'pie',
        radius: ['30%', '55%'],
        labelLine: { // 設置指示線的長度
          normal: {
            length: 8,
            length2: 8
          }
        },
        label: {
          normal: {
            formatter: '{b|{b}:}\n{c}\n{per|{d}%} ',
            rich: {
              b: {
                fontSize: 12,
                lineHeight: 20,
                align: 'center' // 設置文字居中
              },
              per: {
                color: '#eee',
                backgroundColor: '#334455',
                padding: [2, 4],
                borderRadius: 2,
                align: 'center',
              }
            }
          }
        },
        data: dataArray || [
          { value: 135, name: '視頻廣告' },
          { value: 148, name: '百度' },
          { value: 251, name: '谷歌' },
        ]
      }
    ]
  };
  return option;
}
module.exports = getOption;

4、頁面佈局和具體實現

一、report-detail.wxml 佈局頁面

<view>
  <view class="detail-head">
    <text>{{caption}}月報</text>
  </view>
  <text class="caption-sub">數據來源</text>
  <view class="desc">
    <text>截止</text>
    <text>{{caption}}</text>
    <text> {{contentTxt}}</text>
    <text class="data-list-num">{{spaceNum}}</text>
    <text>條,其中:</text>
    <view class="data-list">
      <view>
        <text>存量數據導入:</text>
        <text class="data-list-num">{{stockNum}}</text>
        <text>條;</text>
      </view>
      <view>
        <text>異構接入數據:</text>
        <text class="data-list-num">{{specialNum}}</text>
        <text>條;</text>
      </view>
      <view>
        <text>互聯網抓取數據:</text>
        <text class="data-list-num">{{internetNum}}</text>
        <text>條;</text>
      </view>
    </view>
  </view>
  <view class="echart_panel">
    <ec-canvas id="sorce-pie" canvas-id="source-pie" ec="{{ecLine}}" bind:init="echartInit_source"></ec-canvas>
  </view>
   <view class="hr"></view>
  <view class="echart_panel">
    <ec-canvas id="type-pie" canvas-id="type-pie" ec="{{ecLineSeason}}" bind:init="echartInit_type"></ec-canvas>
  </view>
</view>

二、report-detail.js加載頁面數據

import * as echarts from '../../../ec-canvas/echarts';
var getOptionByExternalJs = require('../../../echart-template/echart-option-config.js');
var optionConfig = new getOptionByExternalJs();
Page({

  /** * 頁面的初始數據 */
  data: {
    contentTxt: '平臺經過存量數據導入,異構數據導入、異構系統/平臺計入及互聯網抓取方式,共聚集空間信息數據',
    spaceNum: 23423,
    stockNum: 234422,
    specialNum: 347458,
    internetNum: 89079,
    ecLine: {},
    ecLineSeason: {}
  },

  /** * 生命週期函數--監聽頁面加載 */
  onLoad: function(options) {
    // 接收上一個頁面傳入的年、季、月
    var month = options.month;
    var year = options.year;
    var season = options.season;
    // 將其掛載到data便於頁面使用
    this.setData({
      caption: year + month
    });
    this.printPie(); // 打印餅圖
  },
  /** * 打印餅圖 * */
  printPie: function() {
    let that = this;
    // 初始化echarts ,同時掛載到data

    wx.showLoading({
      title: '數據加載中......',
    })
    // 此處假設咱們使用wx.requiest請求後臺獲取到了所需數據,重置option
    //打印第一個圖形 [數據來源]
    setTimeout(function() {
      that.loadEchartsByBackstage(
        that.data.initchartSource,
        '數據來源',
        '當月月報', [{
            value: 9432,
            name: '互聯網抓取數據'
          },
          {
            value: 24123,
            name: '存量導入數據'
          },
          {
            value: 14242,
            name: '異構接入數據'
          }
        ]);
      //打印第二個圖形【數據分類】
      that.loadEchartsByBackstage(
        that.data.initchartType,
        '數據分類',
        '當前季度', [{
            value: 19432,
            name: '春節'
          },
          {
            value: 24123,
            name: '秋季'
          },
          {
            value: 14242,
            name: '夏季'
          },
          {
            value: 24242,
            name: '冬季'
          }
        ]);
      wx.hideLoading();
    }, 200);
  },
  /** * 初始化echats * @return {Object} echart * */
  initChart: function(canvas, width, height) {
    const chart = echarts.init(canvas, null, {
      width: width,
      height: height
    });
    canvas.setChart(chart);
    chart.setOption(optionConfig);
    return chart;
  },
  // 來源
  echartInit_source(e) {
    this.data.initchartSource = this.initChart(e.detail.canvas, e.detail.width, e.detail.height);
  },
  //分類
  echartInit_type(e) {
    this.data.initchartType = this.initChart(e.detail.canvas, e.detail.width, e.detail.height);
  },
  /** * 從服務器獲取數據 * */
  loadEchartsByBackstage: function(echarCasch, title, seriesName, dataArray) {
    echarCasch.setOption({
      title: {
        text: title
      },
      series: [{
        name: seriesName,
        data: dataArray
      }]
    });
  }
})

三、report-detail.json 引入echarts

{
  "navigationBarTitleText": "報告詳情",
  "usingComponents": {
    "ec-canvas": "../../../ec-canvas/ec-canvas"
  }
}

四、report-detail.wxss 設置頁面樣式

.detail-head {
  margin-left: 12px;
  font-weight: 700;
}

.caption-sub {
  margin-left: 12px;
  font-size: 12px;
  font-weight: bold;
}

.desc {
  margin: 12px;
  font-size: 14px;
  line-height: 28px;
}
.data-list{
  display: flex;
  flex-direction: column;
}
.data-list-num{
  color:#3cbaff;
}
.echart_panel{
  width: 100%;
  height: 600rpx;
}
.hr {
  border: 1px solid #ccc;
  opacity: 0.2;
  width: 78%;
  margin: 0 auto;
  background-color: red;
  margin-bottom: 20px;
}

5、測試真機運行異常

上面代碼在電腦模擬運行徹底沒問題,可是使用真機測試就會報錯,以下圖
在這裏插入圖片描述git

WAService.js:1 thirdScriptError
Cannot read property 'setOption' of undefined;at pages/analysis-report/report-detail/report-detail onLoad function;at setTimeout callback function
TypeError: Cannot read property 'setOption' of undefined
    at ge.loadEchartsByBackstage (weapp:///pages/analysis-report/report-detail/report-detail.js:110:16)
    at Function.<anonymous> (weapp:///pages/analysis-report/report-detail/report-detail.js:54:12)
    at WAService.js:1:102995
    at Timeout._onTimeout (WAService.js:1:90534)
    at listOnTimeout (internal/timers.js:535:17)
    at processTimers (internal/timers.js:479:7)

一直糾結於爲何setOption未定義,找了很久都沒明白爲啥!
最後改了無數次代碼,想到了多是初始化echarts實例並未完成,就使用setTimeout模擬後臺請求數據,
形成了在調用loadEchartsByBackstage時傳入的that.data.initchartSource,
其實就是一個undefined(由於echartInit_source函數還沒有初始完,
理所固然此時將ecahrts掛載到data中的操做也尚未執行)因此會有如上錯誤github



最後我將setTimeout延時加長問題就沒有了json

/** * 打印餅圖 * */
  printPie: function () {
    let that = this;
    // 初始化echarts ,同時掛載到data

    wx.showLoading({
      title: '數據加載中......',
    })
    // 此處假設咱們使用wx.requiest請求後臺獲取到了所需數據,重置option
    //打印第一個圖形 [數據來源]
    setTimeout(function () {
      ...
    }, 2000);

可是這個確定不是最終的處理辦法(假如應用出現初始化卡頓,延時是否就不夠了呢)!canvas



最後想到了使用promise 來先得到echarts 實例promise

/** * 初始化echats * 使用promise獲取初始化echarts 實例 * @return {Object} echart * */
  initChart: function (canvas, width, height) {
    return new Promise(resolve => {
      const chart = echarts.init(canvas, null, {
        width: width,
        height: height
      });
      canvas.setChart(chart);
      chart.setOption(optionConfig);
      resolve(chart);
    });
  },

再將onload中的printPie()函數移到echarts的初始化中,再在data掛載變量標識printPie()是否已經被調用,若是未調用就調用該函數模擬獲取數據從新渲染option;這樣就OK了。服務器

// 來源
  echartInit_source(e) {
     this.initChart(e.detail.canvas, e.detail.width, e.detail.height).then(res => {
       this.data.initchartSource = res;
       // 判斷因此echarts 實例都初始完畢;而且invokePrintPie爲false
       if (this.data.initchartType && this.data.initchartSource && !this.data.invokePrintPie){
         this.printPie(); // 打印餅圖
         this.data.invokePrintPie = true;
       }
       return res;
    });
  },

修改後的report-detail.js完整代碼微信

import * as echarts from '../../../ec-canvas/echarts';
var getOptionByExternalJs = require('../../../echart-template/echart-option-config.js');
var optionConfig = new getOptionByExternalJs();
Page({

  /** * 頁面的初始數據 */
  data: {
    contentTxt: '平臺經過存量數據導入,異構數據導入、異構系統/平臺計入及互聯網抓取方式,共聚集空間信息數據',
    spaceNum: 23423,
    stockNum: 234422,
    specialNum: 347458,
    internetNum: 89079,
    invokePrintPie:false,//標識是否已經調用打印餅圖操做
    ecLine: {},
    ecLineSeason: {}
  },

  /** * 生命週期函數--監聽頁面加載 */
  onLoad: function (options) {
    // 接收上一個頁面傳入的年、季、月
    var month = options.month;
    var year = options.year;
    var season = options.season;
    // 將其掛載到data便於頁面使用
    this.setData({
      caption: year + month
    });
    //this.printPie(); // 打印餅圖
  },
  /** * 打印餅圖 * */
  printPie: function () {
    let that = this;
    // 初始化echarts ,同時掛載到data

    wx.showLoading({
      title: '數據加載中......',
    })
    // 此處假設咱們使用wx.requiest請求後臺獲取到了所需數據,重置option
    //打印第一個圖形 [數據來源]
    setTimeout(function () {
      that.loadEchartsByBackstage(
        that.data.initchartSource,
        '數據來源',
        '當月月報', [{
          value: 9432,
          name: '互聯網抓取數據'
        },
        {
          value: 24123,
          name: '存量導入數據'
        },
        {
          value: 14242,
          name: '異構接入數據'
        }
        ]);
      //打印第二個圖形【數據分類】
      that.loadEchartsByBackstage(
        that.data.initchartType,
        '數據分類',
        '當前季度', [{
          value: 19432,
          name: '春節'
        },
        {
          value: 24123,
          name: '秋季'
        },
        {
          value: 14242,
          name: '夏季'
        },
        {
          value: 24242,
          name: '冬季'
        }
        ]);
      wx.hideLoading();
    }, 200);
  },
  /** * 初始化echats * 使用promise獲取初始化echarts 實例 * @return {Object} echart * */
  initChart: function (canvas, width, height) {
    return new Promise(resolve => {
      const chart = echarts.init(canvas, null, {
        width: width,
        height: height
      });
      canvas.setChart(chart);
      chart.setOption(optionConfig);
      resolve(chart);
    });
  },
  // 來源
  echartInit_source(e) {
     this.initChart(e.detail.canvas, e.detail.width, e.detail.height).then(res => {
       this.data.initchartSource = res;
       // 判斷因此echarts 實例都初始完畢;而且invokePrintPie爲false
       if (this.data.initchartType && this.data.initchartSource && !this.data.invokePrintPie){
         this.printPie(); // 打印餅圖
         this.data.invokePrintPie = true;
       }
       return res;
    });
  },
  //分類
  echartInit_type(e) {
    this.initChart(e.detail.canvas, e.detail.width, e.detail.height).then(res => {
      this.data.initchartType = res;
      // 判斷因此echarts 實例都初始完畢;而且invokePrintPie爲false
      if (this.data.initchartType && this.data.initchartSource && !this.data.invokePrintPie) {
        this.printPie(); // 打印餅圖
        this.data.invokePrintPie = true;
      }
      return res;
    });
   
  },
  /** * 從服務器獲取數據 * */
  loadEchartsByBackstage: function (echarCasch, title, seriesName, dataArray) {
    echarCasch && echarCasch.setOption({
      title: {
        text: title
      },
      series: [{
        name: seriesName,
        data: dataArray
      }]
    });
  }
})

6、修改後真機預覽

預覽以下圖 :app

加載以前使用默認數據 模擬加載真實數據後

7、 字體大小沒法控制

不知道你們又沒注意到,echarts 的title 有些小呢?然而echarts 的optin中title 設置的字體大小是36了呢。

運行時截圖 option字體設置如圖

最終的解決辦法是去官網定製了一個新的library;
也能夠在雲盤直接下載:雲盤地址 https://pan.baidu.com/s/1kSsYfI0M36KVc1JdeEjvBA 提取碼 lrpg
,如圖:

定製柱狀、折線、餅圖圖表 定製所需組件
下載定製的library 編譯完成自動下載

最後將下載的echarts-mini.js更名爲echarts.js 替換ec-canvas目錄下載的echarts.js便可
在這裏插入圖片描述

相關文章
相關標籤/搜索