组件说明: 由于项目中柱状图、折线图等echarts图表的基本样式几乎相同,如坐标轴样式、网格线等。所以封装成组件,用到echarts的地方,直接引入组件,传数据即可。
小tip:
- 目前只是单个series系列的echarts, 堆叠图这种多系列的后续完善
- 组件未完善功能, 如echarts的点击功能还没来得及做,后续完善
组件接收的参数:
- type: echarts图表的类型,如bar、line、pie、strip(这个并不是官网的标准,这里是用来表示横向柱状图的)
- optData: echarts图表的option
const props = defineProps({
type: String, // bar 、 line
optData: Object,
})
组件模板部分很简单,如下:
<template>
<view>
<view><l-echart class="chart" ref="chart" @finished="init"></l-echart></view>
</view>
</template>
组件数据,这里默认设置了bar、line、pie、strip
四种基本图
let barOption = {
legend:{
show:true,
data:[]
},
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'cross'
}
},
grid: {
left: '3%',
right: '8%',
top: '15%',
bottom:'5%',
containLabel: true
},
xAxis: {
type: 'category',
data: [],
axisLabel: {
// inside: true,
// color: '#fff'
},
axisTick: {
show: false
},
axisLine: {
show: true,
lineStyle:{
color: '#83bff6'
}
},
z: 10
},
yAxis: {
type: 'value',
axisLine: {
show: true,
lineStyle:{
color: '#83bff6'
}
},
axisTick: {
show: false
},
// axisLabel: {
// color: '#999'
// },
splitLine:{
show:true,
lineStyle:{
type: 'dashed',
color: '#83bff6'
}
}
},
series: [
{
data: [],
type: "bar",
itemStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{ offset: 0, color: '#83bff6' },
{ offset: 0.5, color: '#188df0' },
{ offset: 1, color: '#188df0' }
])
},
emphasis: {
itemStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{ offset: 0, color: '#2378f7' },
{ offset: 0.7, color: '#2378f7' },
{ offset: 1, color: '#83bff6' }
])
}
},
areaStyle: {
show: true,
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{
offset: 0,
color: '#188df0'
},
{
offset: 1,
color: '#fff'
}
])
},
}
],
color:['#83bff6']
}
let stripOption = {
legend:{
show:true,
data:[]
},
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'cross'
}
},
grid: {
left: '3%',
right: '8%',
top: '15%',
bottom:'5%',
containLabel: true
},
yAxis: {
type: 'category',
data: [],
axisLabel: {
// inside: true,
// color: '#fff'
},
axisTick: {
show: false
},
axisLine: {
show: true,
lineStyle:{
color: '#83bff6'
}
},
z: 10
},
xAxis: {
type: 'value',
axisLine: {
show: true,
lineStyle:{
color: '#83bff6'
}
},
axisTick: {
show: false
},
// axisLabel: {
// color: '#999'
// },
splitLine:{
show:true,
lineStyle:{
type: 'dashed',
color: '#83bff6'
}
}
},
series: [
{
data: [],
type: "bar",
itemStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{ offset: 0, color: '#83bff6' },
{ offset: 0.5, color: '#188df0' },
{ offset: 1, color: '#188df0' }
])
},
emphasis: {
itemStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{ offset: 0, color: '#2378f7' },
{ offset: 0.7, color: '#2378f7' },
{ offset: 1, color: '#83bff6' }
])
}
},
areaStyle: {
show: true,
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{
offset: 0,
color: '#188df0'
},
{
offset: 1,
color: '#fff'
}
])
},
}
],
color:['#83bff6']
}
let pieOption = {
color:["#2f7ce2","#5bc9b6","#ffc851","#ff6f6f","#7cb3ff","#21949b","#a6a4ff","#ff9e73"],
tooltip: {
show: true,
trigger: 'item',
// formatter: (params) => {
// console.log(params)
// }
},
legend: {
top: '1%',
left: 'center'
},
series: [
{
type: 'pie',
radius: ['30%', '50%'],
avoidLabelOverlap: false,
emphasis: {
label: {
show: true,
fontSize: '40',
fontWeight: 'bold'
}
},
data: []
}
]
};
let chartOption = {
line: barOption,
bar: barOption,
pie: pieOption,
strip: stripOption
}
根据type参数,渲染图表:
const state = reactive({
option:{},
})
function refreshOption(){
state.option = chartOption[props.type];
state.option.series[0].type = props.type;
if(props.type !== "pie" && props.type !== "strip"){
state.option.xAxis.data = props.optData.xData;
}
if(props.type === "strip"){
state.option.yAxis.data = props.optData.xData;
state.option.series[0].type = "bar";
}
state.option.series[0].data = props.optData.yData;
if(props.optData.legendData){
state.option.legend.data = props.optData.legendData;
state.option.series[0].name = props.optData.legendData[0];
}
chart.value.init(echarts, chart => {
chart.setOption(state.option);
});
}
onMounted(() => {
refreshOption()
})
组件向外暴露的方法,只有向外暴露了组件外才能访问到以下内容:
defineExpose({
chart,
refreshOption
})
使用组件
<template>
<view class="container">
<view class="charts-box">
<echart ref="lineChart" type="line" :optData="state.optLine" />
</view>
<uni-card title="月用电量情况">
<view class="charts-box">
<echart type="bar" :optData="state.optBar" />
</view>
</uni-card>
</view>
</template>
const state = reactive( {
optLine: {},
optBar: {},
})
state.optLine = {
xData: [1,2, 3, 4, 5, 6, 7,8,9,10,11,12,13,1,4,15,16,17,18,19,20,21,22,23,24],
yData: [100, 110, 113, 126, 143, 158, 165,167,152,102,,],
}
state.optBar = {
xData: [1,2, 3, 4, 5, 6, 7,8,9,10,11,12,13,1,4,15,16,17,18,19,20,21,22,23,24],
yData: [100, 110, 113, 126, 143, 158, 165,167,152,102,,],
legendData: ['总功率'],
}
动态更新数据时可调用以下方法:
function btnClick(btn){
// change line
state.optLine = {
xData: [1,2, 3, 4, 5, 6, 7,8,9,10,11,12,13,1,4,15,16,17,18,19,20,21,22,23,24],
yData: [100, 110, 113, 126, 143, 158, 165,167,152,102,156,126,180],
}
// delay use,because connot mount
nextTick(() => {
lineChart.value.refreshOption();
})
}
注:这里需要在nextTick中调用组件之前暴露出的refreshOption方法更新数据
效果图:
另外饼图和横向柱状图的使用也一样,效果图如下: