示例簡介
本文介紹使用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);
}
});