• 小程序使用echarts 在一个页面打印多个饼图的坑


    一、下载echarts微信版

    下载地址:https://github.com/ecomfe/echarts-for-weixin
    或者直接云盘下载 https://pan.baidu.com/s/1iOXILEZlmGYzzSin_TK22A 提取码 fwhx

    二、创建所需文件

    同时将下载的echarts 文件拷入,目录如下
    在这里插入图片描述

    三、创建一个配置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}:}
    {c}
    {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;
    

    四、页面布局和具体实现

    1、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>
    

    2、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
          }]
        });
      }
    })
    

    3、report-detail.json 引入echarts

    {
      "navigationBarTitleText": "报告详情",
      "usingComponents": {
        "ec-canvas": "../../../ec-canvas/ec-canvas"
      }
    }
    
    

    4、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;
    }
    
    

    五、测试真机运行异常

    上面代码在电脑模拟运行完全没问题,但是使用真机测试就会报错,如下图
    在这里插入图片描述

    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中的操作也还没有执行)所以会有如上错误



    最后我将setTimeout延时加长问题就没有了

    /**
       * 打印饼图
       * 
       */
      printPie: function () {
        let that = this;
        // 初始化echarts ,同时挂载到data
    
        wx.showLoading({
          title: '数据加载中......',
        })
        // 此处假设我们使用wx.requiest请求后台获取到了所需数据,重置option
        //打印第一个图形 [数据来源]
        setTimeout(function () {
          ...
        }, 2000);
    

    但是这个肯定不是最终的处理办法(假如应用出现初始化卡顿,延时是否就不够了呢)!



    最后想到了使用promise 来先获得echarts 实例

      /**
     * 初始化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
          }]
        });
      }
    })
    
    

    六、修改后真机预览

    预览如下图 :

    加载之前使用默认数据
    模拟加载真实数据后

    七、 字体大小无法控制

    不知道大家又没注意到,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即可
    在这里插入图片描述

  • 相关阅读:
    Scala--基础
    maven
    Storm 运行例子
    Storm 安装部署
    Storm
    Kafka 集群部署
    Redis Twemproxy
    Redis Sentinel
    获取URL中参数的值
    浏览器滚动条样式
  • 原文地址:https://www.cnblogs.com/dengxiaoning/p/11681250.html
Copyright © 2020-2023  润新知