评论

[开盖即食]小程序图表插件 ECharts 实战

ECharts 图表(折线图,饼图,柱形图等)组件实战及一些注意事项

H5时代用来做图表的插件有很多比如:EChartsBizchartsJSCharts等,而这次的小程序本人选用了 ECharts 作为图表组件。

1、选择原因主要有3点:

  • 官方某度在持续维护这个插件
  • 官方推出了直接适配小程序的版本,且有demo,开盖即食,不用迁移
  • 简单实用,覆盖面广且可通过配置控制包的大小,小程序毕竟大小有限制~

eCharts来自BAT中的B前端团队,对应的小程序版本为:echarts-for-weixin

官网地址

https://echarts.apache.org/

github地址

https://github.com/ecomfe/echarts-for-weixin

小程序demo地址

https://github.com/ecomfe/echarts-examples

2、用法

(1)官方教程

index.json 配置如下:

{
  "usingComponents": {
    "ec-canvas": "../../ec-canvas/ec-canvas"
  }
}

这一配置的作用是,允许我们在 pages/bar/index.wxml 中使用 <ec-canvas> 组件。注意路径的相对位置要写对,如果目录结构和本例相同,就应该像上面这样配置。

index.wxml 中创建了一个 <ec-canvas> 组件:

<view class="container">
  <ec-canvas id="mychart-dom-bar" canvas-id="mychart-bar" ec="{{ ec }}"></ec-canvas>
</view>

其中 ec 是一个我们在 index.js 中定义的对象,它使得图表能够在页面加载后被初始化并设置。

index.js 配置:

function initChart(canvas, width, height, dpr) {
  const chart = echarts.init(canvas, null, {
    width: width,
    height: height,
    devicePixelRatio: dpr // 像素
  });
  canvas.setChart(chart);

  var option = {
    ...
  };
  chart.setOption(option);
  return chart;
}

Page({
  data: {
    ec: {
      onInit: initChart
    }
  }
});

这对于所有 ECharts 图表都是通用的,用户只需要修改上面 option 的内容,即可改变图表。option 的使用方法参见 ECharts 配置项文档

官方demo里的一些用法指导:

如何延迟加载图表?

参见 pages/lazyLoad 的例子,可以在获取数据后再初始化数据。

如何在一个页面中加载多个图表?

参见 pages/multiCharts 的例子。

如何使用 Tooltip?

目前,本项目已支持 ECharts Tooltip,但是由于 ECharts 相关功能尚未发版,因此需要使用当前本项目中 ec-canvas/echarts.js,这个文件包含了可以在微信中使用 Tooltip 的相关代码。目前在 ECharts 官网下载的 echarts.js 还不能直接替换使用,等 ECharts 正式发版后即可。
具体使用方法和 ECharts 相同,例子参见 pages/line/index.js

如何保存为图片?

参见 pages/saveCanvas 的例子。

(2)本人实战操作

import * as echarts from '../ec-canvas/echarts';
const app = getApp();
let chart;

function initChart(canvas, width, height, dpr) {
  chart = echarts.init(canvas, null, {
    width: width,
    height: height,
    devicePixelRatio: dpr // new
  });
  canvas.setChart(chart);

  chart.setOption(option);
  return chart;
}
var option = {
  title: {
    text: '智酷君 echarts 切换效果测试',
    left: 'center'
  },
  tooltip: {
      trigger: 'item',
      formatter: '{a} <br/>{b}: {c} ({d}%)'
  },
  legend: {
      orient: 'vertical',
      left: 10,
      data: ['AAA', 'BBB', 'CCC', 'DDD', 'EEE']
  },
  series: [
      {
          name: '访问来源',
          type: 'pie',
          radius: ['50%', '70%'],
          avoidLabelOverlap: false,
          label: {
              show: false,
              position: 'center'
          },
          emphasis: {
              label: {
                  show: true,
                  fontSize: '30',
                  fontWeight: 'bold'
              }
          },
          labelLine: {
              show: false
          },
          data: [
              {value: 335, name: 'AAA'},
              {value: 310, name: 'BBB'},
              {value: 234, name: 'CCC'},
              {value: 135, name: 'DDD'},
              {value: 1548, name: 'EEE'}
          ]
      }
  ]
};

Page({
  data: {
    ec: {
      onInit: initChart
    }
  },
  onLoad: function () {},
  //单曲线
  line() {
    let option2 = {
      title: {
        text: '同一canvas更新成折线图',
        left: 'center'
      },
      xAxis: {
        type: 'category',
        data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
      },
      yAxis: {
        type: 'value'
      },
      series: [{
        data: [820, 932, 901, 934, 1290, 1330, 1320],
        type: 'line'
      }]
    };
    chart.setOption(option2)
  },
  //切换柱状图
  bar(){
    let option3 = {
      title: {
        text: '直接更新数据,减少性能消耗',
        left: 'center'
      },
      xAxis: {
          type: 'category',
          data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
      },
      yAxis: {
          type: 'value'
      },
      series: [{
          data: [120, 200, 150, 80, 70, 110, 130],
          type: 'bar',
          showBackground: true,
          backgroundStyle: {
              color: 'rgba(220, 220, 220, 0.8)'
          }
      }]
    };
    chart.setOption(option3)
  }
})

建议大家尽量使用同一个canvas对象来切换不同的图表效果,而不是初始加载多个不同的,我们可以将 chart 对象设置为全局,然后通过 chart.setOption() 的方法来更新配置数据,可以减少性能消耗避免闪退等

(3)代码片段

代码段:https://developers.weixin.qq.com/s/OOTwnsms7Cin

建议将IDE工具升级到 1.02.18以上,避免一些BUG

3、Tips

(1)包大小可以配置

在线定制地址:

https://echarts.apache.org/zh/builder.html

通过选择和配置想要的功能,可以大大减少原本JS包的尺寸。

(2)Canvas 2d 版本要求

最新版的 ECharts 微信小程序支持微信 Canvas 2d,当用户的基础库版本 >= 2.9.0 且没有设置 force-use-old-canvas="true" 的情况下,使用新的 Canvas 2d(默认)。

使用新的 Canvas 2d 可以提升渲染性能,解决非同层渲染问题,强烈建议开启

如果仍需使用旧版 Canvas,使用方法如下:

<ec-canvas id="xxx" canvas-id="xxx" ec="{{ ec }}" force-use-old-canvas="true"></ec-canvas>

(3)数据点过多造成闪退和卡死

本人简单测试了下,iphone7p手机在1500个左右数据点的时候,出现了小程序闪退,iphoneX 测试下来大概在2500个左右,猜测可能由于微信本身给小程序的内存有限,所以建议大家控制数据点的个数

(4)单页面图表canvas加载过多卡死

建议单页面图表加载不要超过5个canvas,尽可能共用一个图表Canvas对象,通过动态更新数据的方式来展示内容(还有帅气的特效),如果一定要加载多个canvas的话,建议控制数量,提供复用性~

看完觉得有帮助记得点个赞哦~

你的赞是我继续分享的最大动力!^-^

最后一次编辑于  2020-06-29  
点赞 23
收藏
评论

18 个评论

  • 余冲😛
    余冲😛
    2021-02-20

    入坑警告:不支持PC

    2021-02-20
    赞同 2
    回复 3
    • 游戏人生
      游戏人生
      2021-02-20
      对的,这个不知道baidu未来会不会优化,但是PC小程序不作为优先项
      2021-02-20
      1
      回复
    • 余冲😛
      余冲😛
      2021-03-14
      解决了,分享一下。pc版不支持canvas 2d 所以在ec-canvas里写上 force-use-old-canvas=“{{true}}”;就可以了。贴上代码:
      2021-03-14
      1
      回复
    • 唐同学
      唐同学
      2021-08-30
      致命硬伤,报错TypeError: Cannot read property 'getContext' of null
      2021-08-30
      回复
  • 星星火燎原
    星星火燎原
    2021-03-03

    问题描述:option使用数据集dataset的方式配置后,图表报错

    使用你的demo,经反复测试,有一个很大的问题,如果option使用数据集dataset的方式配置后,图表不能渲染出来,在开发者工具控制台报错“TypeError: t.count is not a function”,不知如何解决,还请楼主查看回复此问题!

    问题重现:将楼主的line方法里的option改为echarts官方数据集方式的条形图配置,运行并点击按钮

    echarts官方数据集示例:

    https://echarts.apache.org/examples/zh/editor.html?c=data-transform-sort-bar

    //单曲线
      line() {
        let option2 = {
          dataset: [{
            dimensions: ['name''age''profession''score''date'],
            source: [
              [' Hannah Krause '41'Engineer'314'2011-02-12'],
              ['Zhao Qian '20'Teacher'351'2011-03-01'],
              [' Jasmin Krause '52'Musician'287'2011-02-14'],
              ['Li Lei'37'Teacher'219'2011-02-18'],
              [' Karle Neumann '25'Engineer'253'2011-04-02'],
              [' Adrian Groß'19'Teacher'null'2011-01-16'],
              ['Mia Neumann'71'Engineer'165'2011-03-19'],
              [' Böhm Fuchs'36'Musician'318'2011-02-24'],
              ['Han Meimei '67'Engineer'366'2011-03-12'],
            ]
          }, {
            transform: {
              type'sort',
              config: { dimension: 'score', order: 'desc' }
            }
          }],
          xAxis: {
            type'category',
            axisLabel: { interval: 0, rotate: 30 },
          },
          yAxis: {},
          series: {
            type'bar',
            encode: { x: 'name', y: 'score' },
            datasetIndex: 1
          }
        };
        chart.setOption(option2)
      }
    

    示例图:


    2021-03-03
    赞同 1
    回复 1
  • TOM
    TOM
    09-25

    初始化之后要怎么更改option中的值动态刷新图表

    09-25
    赞同
    回复
  • 苌凯旋
    苌凯旋
    07-09

    请问pages/saveCanvas保存图片的示例在哪里?

    07-09
    赞同
    回复 1
    • 游戏人生
      游戏人生
      07-10
      会获得一个以temp开头的临时地址
      07-10
      回复
  • 曾是少年
    曾是少年
    2022-10-25

    请问小程序上面可以实现y轴的标签在中间吗?这个怎么实现

    2022-10-25
    赞同
    回复
  • 雨帆
    雨帆
    2022-04-10

    你好,我用自己定制的echarts.js替换了原来echarts.js时报了错,更新了版本也没用,这种的话,有什么解决方法吗

    2022-04-10
    赞同
    回复
  • 康哥
    康哥
    2022-03-21

    formatter不支持自定义标签吗?

    2022-03-21
    赞同
    回复
  • Smlie
    Smlie
    2022-02-14

    在添加markPoint时,使用自定义图片,new Image()会报错,这个如何解决?

    echarts版本4.8

    2022-02-14
    赞同
    回复 1
  • 标弟
    标弟
    2021-12-16

    legend这个属性需要配置什么吗 我好像在option里面些legend这个属性 然后都不显示出来?

    2021-12-16
    赞同
    回复
  • 十二月
    十二月
    2021-01-13

    你好,图表加载出来后,点击按钮进行保存echart图表没有反应,请问是什么问题?

    this.echartsComponnet = this.selectComponent('#mychart');

    下载代码

      setTimeout(()=>{

          console.log("setTimeout==============")

    //后面的console都没有打印

          this.echartsComponnet.canvasToTempFilePath({

            success: res => {

              console.log("success=====res.tempFilePath:", res.tempFilePath)

              // 存入系统相册

              wx.saveImageToPhotosAlbum({

                filePath: res.tempFilePath || '',

                success: res => {

                  console.log("success", res)

                },

                fail: res => {

                  console.log("fail", res)

                  if(res.errMsg === "saveImageToPhotosAlbum:fail:auth denied" || res.errMsg === "saveImageToPhotosAlbum:fail auth deny" || res.errMsg === "saveImageToPhotosAlbum:fail authorize no response"{

                    wx.showModal({

                      title: '提示',

                      content: '需要您授权保存相册',

                      showCancel: false,

                      success: modalSuccess => {

                        wx.openSetting({

                          success(settingdata) {

                            if (settingdata.authSetting['scope.writePhotosAlbum']) {

                              console.log('获取权限成功,给出再次点击图片保存到相册的提示。')

                            }else {

                              console.log('获取权限失败,给出不给权限就无法正常使用的提示')

                            }

                          }

                        })

                      }

                    })       

                  }

                }

              })

            },

            fail: res => console.log("fail======",res)

          })

        },500)

       


    2021-01-13
    赞同
    回复

正在加载...

登录 后发表内容