最近项目在集成图表到小程序,把这其中遇到的问题记录下来,以便查询。
最终效果
首先想到的是Echarts,毕竟是国内团队做的Apache顶级项目,有保证。而且官方也支持在小程序中使用。在查阅资料中又发现了ucharts这个项目,也是国内团队,但国际化程度不高,只在码云上开源,而且据说文档很一般。
上面效果图就是使用懒加载的效果,进入页面后,开始请求数据,获取到数据后再进行初始化echarts。懒加载的作用就是实现先准备数据后初始化图表
import * as echarts from '../ec-canvas/echarts';
const app = getApp();
function setOption(chart, data) {
let option = {
backgroundColor: "#ffffff",
tooltip: {
trigger: 'item',
formatter: //'{b}: {c} ({d}%)'
function (params) {
var groupName = params.value.groupName;
return '{groupName|' + groupName + '}';
}
},
legend: {
orient:'horizontal',
left: 'center'
},
dataset: {
dimensions: ['deposit', 'groupName', 'integral', 'money', 'quantity'],
source: data
},
series: [{
name: 'legend',
label: {
formatter: function (params) {
var groupName = params.value.groupName;
var quantity = params.value.quantity;
var percent = params.percent;
return '{groupName|' + groupName + ': '+ '}' + '{quantity|' + quantity + '}吨' + ' {per|' + percent + '%}';
},
backgroundColor: '#F6F8FC',
borderColor: '#8C8D8E',
borderWidth: 1,
borderRadius: 4,
rich: {
groupName: {
color: '#4C5058',
fontSize: 14,
fontWeight: 'bold',
lineHeight: 33
},
per: {
color: '#fff',
backgroundColor: '#4C5058',
padding: [3, 4],
borderRadius: 4
}
}
},
type: 'pie',
center: ['50%', '50%'],
radius: ['20%', '40%'],
encode: {
name: 'groupName',
value: 'quantity'
}
}]
};
chart.setOption(option);
}
Page({
/**
* 页面的初始数据
*/
data: {
ec: {
lazyLoad: true
},
statisticsData: [],
},
// 初始化图表
_initChart: function () {
this.ecComponent.init((canvas, width, height, dpr) => {
// 获取组件的 canvas、width、height 后的回调函数
// 在这里初始化图表
const chart = echarts.init(canvas, null, {
width: width,
height: height,
devicePixelRatio: dpr // new
});
setOption(chart, this.data.statisticsData);
// 将图表实例绑定到 this 上,可以在其他成员函数(如 dispose)中访问
this.chart = chart;
this.setData({
isLoaded: true,
isDisposed: false
});
// 注意这里一定要返回 chart 实例,否则会影响事件处理等
return chart;
});
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (e) {},
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady: function () {
// 获取组件
this.ecComponent = this.selectComponent('#mychart-dom-pie');
},
// 刷新订单列表及统计信息
_refresh: function () {
// 获取商品统计信息
let productDetailData = {
productCode: "",
};
api.productDetail(productDetailData).then(
(res) => {
this.setData({
statisticsData: res.data.data.statistics,
});
this._initChart();
},
() => {
this.setData({
statisticsData: [],
});
}
);
},
onShow: function () {
// 显示订单卡片及统计信息
this._refresh();
},
});
这里的代码是根据官方提供的懒加载demo进行的微调。其中,为了实现显示页面就自动加载业务数据的效果,我把初始化图表的操作即this._initChart()放在了数据获取的回调函数中,从而保证初始化时一定有数据。而获取组件的操作this.selectComponent(‘#mychart-dom-pie’)放在onReady中,则是因为经过尝试,放在onShow中无法获取,根据官方的时序图,在onShow结束时,视图线程还没有完成初始化。
官方文档中的echarts.js为包含所有图表样式的文件,其体积大于1MB,可官方提供的这个工具进行按需选择,下载后替换就好了
https://echarts.apache.org/zh/builder.html
按上面的配置生成的js文件仅有468KB。
如果你想使用自己的json结构,而不想用下面的结构
[{
"name": xxx,
"value": xxx
}]
就需要使用dataset+encode
{
...
dataset: {
dimensions: ['deposit', 'groupName', 'integral', 'money', 'quantity'],
source: [{'deposit': 1, 'groupName': '测试', 'integral': 1, 'money': 1, 'quantity': 1}]
},
series: [{
...
type: 'pie',
encode: {
name: 'groupName',
value: 'quantity'
}
}]
}
如果你想用字符串模版,而不想用下面的
(1){a}:系列名,series.name。
(2){b}:数据名,series.data.name。
(3){c}:数据值,series.data.value。
(4){d}:百分比。
(5){@xxx}:数据中名为’xxx’的维度的值,如{@product}表示名为’product’ 的维度的值。
(6){@[n]}:数据中维度n的值,如{@[3]}` 表示维度 3 的值,从 0 开始计数。
就要使用函数模版了
{
...
dataset: {
dimensions: ['deposit', 'groupName', 'integral', 'money', 'quantity'],
source: [{'deposit': 1, 'groupName': '测试', 'integral': 1, 'money': 1, 'quantity': 1}]
},
series: [{
...
label: {
formatter: function (params) {
var groupName = params.value.groupName;
var quantity = params.value.quantity;
var percent = params.percent;
return '{groupName|' + groupName + ': '+ '}' + '{quantity|' + quantity + '}吨' + ' {per|' + percent + '%}';
},
type: 'pie',
encode: {
name: 'groupName',
value: 'quantity'
}
}]
}
如果你想给上面的加上样式,就需要rich设置富文本
{
...
dataset: {
dimensions: ['deposit', 'groupName', 'integral', 'money', 'quantity'],
source: [{'deposit': 1, 'groupName': '测试', 'integral': 1, 'money': 1, 'quantity': 1}]
},
series: [{
...
label: {
formatter: function (params) {
var groupName = params.value.groupName;
var quantity = params.value.quantity;
var percent = params.percent;
return '{groupName|' + groupName + ': '+ '}' + '{quantity|' + quantity + '}吨' + ' {per|' + percent + '%}';
},
rich: {
groupName: {
color: '#4C5058',
fontSize: 14,
fontWeight: 'bold',
lineHeight: 33
},
per: {
color: '#fff',
backgroundColor: '#4C5058',
padding: [3, 4],
borderRadius: 4
}
}
},
type: 'pie',
encode: {
name: 'groupName',
value: 'quantity'
}
}]
}
官方提供的demo中有个全局的css文件app.wxss
/**app.wxss**/
.container {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
display: flex;
flex-direction: column;
align-items: center;
justify-content: space-between;
box-sizing: border-box;
}
这里的container与我其他位置的container冲突,导致页面渲染出问题,为了解决这个问题,可以将上面的代码转移到子页面中
一处是你使用echarts图表的页面的css文件中,另一处则是ec-canvas.wxss中