微信小程序实现echarts并兼容IOS

前言

本文介绍使用ec-canvas实现小程序图表功能,支持切换更新数据并在IOS顺畅使用。

Tips:本文只介绍柱形图,其它图形类似,具体可查看GitHub上的ecomfe/echarts-for-weixin项目。

实现过程

1. 文件index.wxml和index.wxss代码如下,这一块比较简单,可自行查看,不做过多分析;

<view class="container">
	<view class="item-head">
		<view class="tit">月份统计</view>
		<picker mode="selector" bindchange="chooseChange" value="{
    
    {chooseIndex}}" range="{
    
    {choossArr}}" range-key="value" name="chooseType" class="picker-box">
			<view class="picker">
				{
    
    {choossArr[chooseIndex].value}}
			</view>
			<image src="../../images/arrow.png"></image>
		</picker>
	</view>
	<view class="echart-heig">
		<image src="{
    
    {echartImgSrc}}" class="echart-img" wx:if="{
    
    {echartImgSrc1 != ''}}"></image>
		<ec-canvas id="mychart" canvas-id="mychart-bar" ec="{
    
    { ec }}" class="{
    
    {echartImgSrc != '' ? 'hide' : ''}}"></ec-canvas>
	</view>
</view>
.container {
  height: 100%;
  display: flex;
  flex-direction: column;
}

.item-head {
  display: flex;
  padding: 40rpx 30rpx 20rpx;
}

.item-head .tit {
  font-size: 30rpx;
  margin: 6rpx 14rpx 0 0;
}

.item-head .picker-box {
  display: flex;
  width: 196rpx;
  height: 50rpx;
  font-size: 26rpx;
  line-height: 50rpx;
  border-radius: 6rpx;
  border: 2rpx solid #e6e6e6;
}

.item-head .picker-box .picker {
  display: inline-block;
  flex: 0.7;
  width: 140rpx;
  text-align: left;
  margin-left: 20rpx;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}

.item-head .picker-box image {
  flex: 0.3;
  width: 12rpx;
  height: 8rpx;
  margin-top: -34rpx;
  vertical-align: middle;
}

.item-head .picker-box.ios image {
  margin-top: -10rpx;
}

.hide {
  display: none !important;
}

.echart-img {
  width: 100%;
  height: 100%;
}

.echart-heig {
  width: 100%;
  height: 1020rpx;
}

2. 文件index.js存放所有功能的逻辑代码,代码实现如下:

1)函数chooseChange用于获取切换数据后的月份;

2)函数getFinishCount用来根据月份判断使用的数据;为了方便使用简单的数据切换,项目情况下,一般都是调用接口获取数据;有个特别要注意的,就是把echartImgSrc的值清空,不然没办法更新数据;

3)函数initEcharts是示例的核心,数据结构可自行查看官网,更新数据使用了chart.setOption(option);但这里有个比较特别的代码,就是先使用canvasToTempFilePath把指定区域生成图片,然后赋值echartImgSrc来重新渲染页面,因为直接用ec-canvas渲染,在IOS滑动会很卡。

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

Page({
  data: {
    villageArr: [],
    villageArr1: [{
        value1: 90,
        value2: 78,
        name: 'aaa'
      },
      {
        value1: 145,
        value2: 120,
        name: 'bbb'
      },
      {
        value1: 98,
        value2: 87,
        name: 'ccc'
      },
      {
        value1: 126,
        value2: 102,
        name: 'ddd'
      },
      {
        value1: 90,
        value2: 90,
        name: 'eee'
      },
      {
        value1: 108,
        value2: 100,
        name: 'fff'
      },
      {
        value1: 134,
        value2: 120,
        name: 'ggg'
      }
    ],
    villageArr2: [{
        value1: 50,
        value2: 45,
        name: 'aaa'
      },
      {
        value1: 40,
        value2: 36,
        name: 'bbb'
      },
      {
        value1: 70,
        value2: 67,
        name: 'ccc'
      },
      {
        value1: 80,
        value2: 54,
        name: 'ddd'
      },
      {
        value1: 77,
        value2: 55,
        name: 'eee'
      },
      {
        value1: 66,
        value2: 57,
        name: 'fff'
      },
      {
        value1: 80,
        value2: 50,
        name: 'ggg'
      }
    ],
    ec: {},
    echartImgSrc: '', // canvas在ios下滑动问题,目前只能将echarts图表渲染完成后再生成为图片展示。
    chooseIndex: 0, // 选中的下标
    choossArr: [{
        value: '1月',
        id: 1
      },
      {
        value: '2月',
        id: 2
      }
    ]
  },
  // 切换不同数据
  getFinishCount: function (month) {
    let self = this;
    if (month === 1) {
      this.setData({
        villageArr: this.data.villageArr1,
        echartImgSrc: ''
      });
    } else {
      this.setData({
        villageArr: this.data.villageArr2,
        echartImgSrc: ''
      });
    }    
    self.initEcharts();
  },
  // 数据渲染
  initEcharts: function (canvas, width, height) {
    let that = this;
    this.selectComponent('#mychart').init((canvas, width, height) => {
      // 初始化图表
      const chart = echarts.init(canvas, null, {
        width: width,
        height: height
      });
      let villageArr = that.data.villageArr;
      let villageArrName = [];
      let villageArrValue1 = [];
      let villageArrValue2 = [];

      villageArr.map(function (item, index) {
        villageArrName.push({
          value: item.name,
          id: index
        });
        villageArrValue1.push({
          value: item.value1
        });
        villageArrValue2.push({
          value: item.value2
        });
      })
      this.setData({
        villageArr: villageArr
      })

      let option = {
        color: ["#58a7f8", "#63e669"],
        legend: {
          data: ['上报量', '完成量'],
          top: 0,
          left: 10,
          icon: 'roundRect',
          itemWidth: 13,
          itemHeight: 13,
          itemGap: 20,
        },
        grid: {
          left: 15,
          right: 25,
          bottom: 0,
          top: 35,
          containLabel: true
        },
        xAxis: {
          type: 'value',
          axisTick: {
            show: false
          },
          axisLine: {
            show: false,
          },
          splitLine: {
            lineStyle: {
              color: '#e6e6e6'
            }
          },
          axisLabel: {
            textStyle: {
              color: '#6a737d'
            }
          }
        },
        yAxis: {
          type: 'category',
          axisTick: {
            show: false
          },
          axisLine: {
            show: false,
          },
          axisLabel: {
            textStyle: {
              color: '#6a737d',
              fontSize: 11,
              align: 'right',
            },
            formatter: function (value, index) {
              if (value.length > 6) return value.slice(0, 6) + '...';
              else return value;
            }
          },
          data: villageArrName
        },
        series: [{
            name: '上报量',
            type: 'bar',
            barWidth: 12,
            barGap: '-100%',
            data: villageArrValue1
          },
          {
            name: '完成量',
            type: 'bar',
            barWidth: 12,
            data: villageArrValue2
          }
        ]
      };

      chart.on('finished', () => {
        that.selectComponent('#mychart').canvasToTempFilePath({
          success: res => {
            that.setData({
              echartImgSrc: res.tempFilePath
            })
            wx.hideLoading();
          },
          fail: res => console.log('转换图片失败', res)
        });
      })

      chart.setOption(option);
      return chart;
    });
  },
  // 选项改变触发
  chooseChange: function (e) {
    wx.showLoading({
      title: '加载中',
      mask: true
    });
    this.setData({
      chooseIndex: e.detail.value
    })
    let month = this.data.choossArr[e.detail.value].id;
    this.getFinishCount(month);
  },
  // 加载页面
  onLoad: function () {
    wx.showLoading({
      title: '加载中',
      mask: true
    });
    // 默认第一月数据
    this.getFinishCount(1);
  }
});

 

 

                                                                             扫描公众号,了解更多实例分享

Guess you like

Origin blog.csdn.net/king0964/article/details/107516789