微信小程序中应用echart图表

3,351 阅读3分钟

ECharts的微信小程序版本

Echarts的官方文档

自定义小程序echart插件图表的点击事件

微信小程序在ios下Echarts图表不能滑动的解决方案

注:echarts.js可以根据本身项目的需要,在echarts的官网上,在线定制下载,以减少文件体积;

一、小程序中echart用法

wxml

<ec-canvas id="mychart-dom-come" canvas-id="come" ec="{{ ecCome }}"></ec-canvas>

index.js

Page({
    data: {
        ecCome: {},
        payWidth:0,
        payHeight:0,
    },
     /**监听页面加载 */
  onLoad: function (options) {
      var that = this;
      var id = options.id;
      
      //创建节点选择器
    const query = wx.createSelectorQuery()
    query.select('.tabCon').boundingClientRect()
    query.selectViewport().scrollOffset()
    query.exec(function (res) {
      res[0].top       // 节点的上边界坐标
      res[1].scrollTop // 显示区域的竖直滚动位置
      that.setData({
        payWidth: res[0].width,  //节点的宽度
        payHeight: res[0].height //节点的高度
      })
    })
    
  },
/**监听页面初次渲染完成,获取自定义子组件 */
  onReady: function () { 
    var that = this;
    that.comeComponent = that.selectComponent('#mychart-dom-come');
  },
  
/* 动态传入数据,获取数据后执行这个方法并传入数据 */
  comeEchartInit: function(list){

    var that = this;
    that.comeComponent.init((canvas, width, height)=>{
    
        //当图表通过display:none隐藏后再显示,不能获取canvas的宽高,需要传入数值
      that.initChartCome(canvas, that.data.payWidth, that.data.payHeight, list);
      
    })
  },
  /*图表初始化*/
  initChartCome: function (canvas, width, height, list) {
   
    const chart = echarts.init(canvas, null, {
      width: width,
      height: height
    });
    canvas.setChart(chart);


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

二、小程序的原生组件使用限制

官方文档说明链接:小程序的原生组件使用限制

1、出现的问题:在图表外层view加点击事件,触发不了事件?

原因:

(1)不论是加大view上的z-index值,还是将absolute改为fixed,ec-canvas组件所渲染的图表就是在view上面,而没有被view遮挡。

图表是一个canvas组件,而小程序中canvas是一个原生组件!!!

(2)由于微信小程序 canvas组件没有提供tap事件,所以导致echart的插件也无法相应tap事件,所以这里需要我们自定义tap事件

解决方法:

自定义小程序echart插件图表的点击事件:

打开插件目录下 ec-canvas.js (tap的原理就是,touchstart----untouchmove----->touchend)添加如下代码:

data: {
    startPoint:false //添加事件标志位
},
...
touchStart(e) {
    //记录标记
   this.data.startPoint = true ;
   ...
},
touchMove(e) {
    //移动了就不能实现tap,所以清空记录标记
    this.data.startPoint = false;
    ...
},
touchEnd(e) {
    //如果没有移动过
   if (this.data.startPoint){
           this.data.startPoint = false;
      //执行点击事件,这里是触发父组件的myevent方法(通常就是调用echart插件的那个页面)
      this.triggerEvent('myevent', {}, {});
   }
}

在调用echart插件的地方,注册myevent

<ec-canvas bindmyevent="test"></ec-canvas>
//test方法写在当前page的js中即可

三、echarts渲染完后转成图片

wxml:

<view class="echart-container">
  <image wx:if="{{echartImgSrc!==''}}" src="{{echartImgSrc}}" class='echart-img'></image>
  <ec-canvas wx:if="{{echartImgSrc===''}}" id="mychart-dom-pie" canvas-id="mychart-pie" ec="{{ ec }}" bind:init="echartInit"></ec-canvas>
</view>

js:

Page({
  data: {
    ec: {
    },
    echartImgSrc: ''
  },
  initChart(canvas, width, height) {
    const chart = echarts.init(canvas, null, {
      width: width,
      height: height
    });
    canvas.setChart(chart);

    var option = {
      // ...
    };
    chart.on('finished', () => {
      this.selectComponent('#mychart-dom-pie').canvasToTempFilePath({
        success: res => {
          this.setData({
            echartImgSrc: res.tempFilePath
          })
        },
        fail: res => console.log('转换图片失败', res)
      });
    })
    chart.setOption(option);
    return chart;
  },

  echartInit(e) {
    this.initChart(e.detail.canvas, e.detail.width, e.detail.height);
  }
});

ec-canvas.js:

//修改后
    canvasToTempFilePath(opt) {
      console.log(opt,this)
      if (!opt.canvasId) {
        opt.canvasId = this.data.canvasId;
      }
      console.log(55,opt.canvasId)
     
      const system = wx.getSystemInfoSync().system
      if (/ios/i.test(system)) {
        ctx.draw(false, () => {
          wx.canvasToTempFilePath(opt, this);
        });
      } else {//针对安卓机型异步获取已绘制图层
        ctx.draw(false, () => {
        
          ctx.draw(false);
          setTimeout(() => {//延迟获取
            wx.canvasToTempFilePath(opt, this);
          }, 1000);
        })
      }
    },
    
注:当交互少的用这个方法可以实现,因为我写的项目中有轮播切换图表,也就是使用了swiper中有canvas,ios中不能进行滑动切换,安卓上可以进行正常切换,并且轮播的数量是通过动态渲染的,通过这个方法,即使加了计时器并在ctx.draw的回调中执行wx.canvasToTempFilePath,但是也不能全部返回路径,之后通过左右按钮来进行切换了。