echarts 自定义配置信息
renderItem 函数提供了两个参数:
一、前移半格
renderItem 实现
option = {
xAxis: {
type: 'category',
data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
},
yAxis: {
type: 'value',
},
series: [
{
type: 'custom',
renderItem:function(params, api){
const xIndex = params.dataIndex;
// 横线
const horizontalPoint = api.coord([xIndex, api.value(0)]);
// 竖线
const verticalPoint = api.coord([xIndex, api.value(1)]);
const halfWidth = api.size([1, 0])[0] * 0.5;
const style = api.style({
stroke: api.visual('color'),
fill: undefined
});
const customObj = {
type: 'group',
children: [
{
//横线
type: 'line',
shape: {
x1: horizontalPoint[0] - halfWidth,
y1: horizontalPoint[1],
x2: horizontalPoint[0] + halfWidth,
y2: horizontalPoint[1]
},
style: style
},
{
//竖线
type: 'line',
shape: {
x1: horizontalPoint[0] + halfWidth,
y1: horizontalPoint[1],
x2: verticalPoint[0] + halfWidth,
y2: verticalPoint[1]
},
style: style
},
]
}
const pointDraw = {
// 小圆点-在横线中间
type: 'circle',
x: horizontalPoint[0] + halfWidth,
y: horizontalPoint[1],
shape: {
cx: horizontalPoint[0],
cy: horizontalPoint[1],
r: 2.2
},
style
}
// customObj.children.push(pointDraw)
return customObj;
},
data:[[12, 80], [80, 14], [14, 14], [14, 8], [8]]
}
]
};
效果:
补充
/**
* 自定义数据过滤
* [12, 80, 14, 14, 8] 转成 [[12, 80], [80, 14], [14, 14], [14, 8], [8]]
*/
customDataFilter(data) {
let arr = [];
for (let i = 0; i < data.length; i++) {
if (data[i + 1]) {
arr.push(['', data[i], data[i + 1]]);
} else {
arr.push(['', data[i]]);
}
}
return arr;
},
二、划分多区域
graphic 结合 renderItem 实现
/*
xAxis横坐标数据源
说明:上下限个数必须同横坐标一一对应
格式:[21, 43.5, 64, 84, 100]
*/
var xAxis = [21, 43.5, 64, 84, 100]
/*
seriesData上下限数据源
说明:二维数组,每组length必须相同,下限在前上限在后,必须一一对应
格式:[
[10, 10, 10, 10, 10, 20, 20, 20, 30, 30],//前5个为下限值,后5个为上限值
[50, 50, 50, 50, 50, 70, 70, 70, 80, 80],
[81, 81, 81, 81, 81, 92, 92, 92, 92, 92]
]
markLine 自定义标线
说明:自定义
格式:
{
symbol: 'none', //去掉箭头
data: [
// { type: 'average', name: 'Avg' },
{
yAxis: 20,
symbol: 'circle',
label: {
position: 'middle',
formatter: `装机容量(MW)`
},
lineStyle: {
color: 'red',
dashOffset: 5
// type: 'solid'
}
}
]
}
*/
var seriesData = [
[10, 10, 10, 10, 10, 20, 20, 20, 30, 30],
[50, 50, 50, 50, 50, 70, 70, 70, 80, 80],
[81, 81, 81, 81, 81, 92, 92, 92, 92, 92]
]
var colorArr = ['#ee6666', '#5470c6', '#91cc75', '#fac858', '#73c0de', '#3ba272', '#fc8452', '#9a60b4', '#8f85f6']
var MyCubeRect = echarts.graphic.extendShape({
shape: {
x: 0,
y: 0
},
buildPath: function (ctx, shape) {
// const xAxis = vm.xAxis;
const api = shape.api;
//处理数据取出上限下限的值
let yMinArr = [];
let yMaxArr = [];
for (let i = 0; i < xAxis.length; i++) {
yMinArr.push(shape['yMin' + i]);
yMaxArr.push(shape['yMax' + i]);
}
//坐标系列
xAxis?.length &&
xAxis.map((item, index) => {
if (index === 0) {
ctx.moveTo(api.coord([xAxis[index], yMinArr[index]])); //起始点
}
const yPoint = api.coord([xAxis[index], yMinArr[index]]);
ctx.lineTo(yPoint[0], yPoint[1]); //1
});
xAxis?.length &&
xAxis.map((item, index) => {
const yPoint = api.coord([xAxis[xAxis.length - index - 1], yMaxArr[xAxis.length - index - 1]]);
ctx.lineTo(yPoint[0], yPoint[1]); //1
});
ctx.closePath();
}
});
echarts.graphic.registerShape('MyCubeRect', MyCubeRect);
var option={
xAxis: {
name: '测试x',
type: 'value'
},
yAxis: {
name: '测试y',
type: 'value'
},
series: [
{
type: 'custom',
data: seriesData,
// markLine: vm.markLine,
renderItem: function (params, api) {
console.log('params: ', params);
let shapeObj = {};
for (let i = 0; i < xAxis.length; i++) {
shapeObj['yMin' + i] = api.value(i);
shapeObj['yMax' + i] = api.value(i + xAxis.length);
}
return {
type: 'group',
children: [
{
type: 'MyCubeRect', // 自定义shape
shape: {
api,
...shapeObj
},
style: {
//边框颜色
stroke: 'rgba(255,255,255,1)',
fill: colorArr[params.dataIndex],
//平面颜色
// fill:{ //渐变
// type: 'linear',
// x: 0,
// y: 0,
// x2: 0,
// y2: 1,
// colorStops: [{
// offset: 0, color: '#3F66EC' // 0% 处的颜色
// }, {
// offset: 1, color: '#8092D0' // 100% 处的颜色
// }],
// global: false // 缺省为 false
// },
// fill: '#4067EB',
// text:seriesData[params.dataIndex],
// textPosition:[10,-20] //文字显示位置
}
}
]
};
}
}
]
};
效果:
注意,这是5.0.0版本效果,其他版本请自测
三、柱状图 设置多个横坐标共用一个柱子
custom 结合 renderItem 实现
const data1 = [
['01月01日', 5, 30, 'a'],
['06月01日', 3, 10, 'b'],
['09月01日', 3, 37, 'c']
].map((item, index) => {
return {
value: item,
itemStyle: {
color: ['#66CCFF', '#ff6699', '#ccff99', '#bce9a6', '#8da2e4'][index]
}
};
});
const data2 = [
['01月01日', 5, 30, 'A'],
['06月01日', 3, 10, 'B'],
['09月01日', 3, 37, 'C']
].map((item, index) => {
return {
value: item,
itemStyle: {
color: ['#a4e0f7', '#ff9b9b', '#ffe68f', '#bce9a6', '#8da2e4'][index]
}
};
});
option = {
title: {
text: '百分比',
left: 'center'
},
tooltip: {},
xAxis: {
type: 'category',
boundaryGap: true,
axisTick: {
alignWithLabel: true
},
data: [
'01月01日',
'02月01日',
'03月01日',
'04月01日',
'05月01日',
'06月01日',
'07月01日',
'08月01日',
'09月01日',
'10月01日',
'11月01日',
'12月01日'
]
},
yAxis: {
max: 100,
min: 0,
splitNumber: 20,
axisLabel: {
formatter: '{value} %'
}
},
series: [
{
type: 'custom',
renderItem: function (params, api) {
var start = api.coord([api.value(0), api.value(2)]);
var size = api.size([api.value(0), api.value(2)]);
var width = params.coordSys.width / 12;
return {
type: 'rect',
shape: {
x: start[0],
y: start[1],
width: width * api.value(1),
height: size[1]
},
style: api.style()
};
},
label: {
show: true,
position: 'inside'
},
dimensions: ['起始日期', '结束日期', 'name'],
encode: {
x: 0,
y: 2,
tooltip: 2,
itemName: 3
},
data: data1
},
{
type: 'custom',
renderItem: function (params, api) {
var start = api.coord([api.value(0), 100]);
var size = api.size([api.value(0), 100 - api.value(2)]);
var width = params.coordSys.width / 12;
return {
type: 'rect',
shape: {
x: start[0],
y: start[1],
width: width * api.value(1),
height: size[1]
},
style: api.style()
};
},
label: {
show: true,
position: 'inside',
color: '#000'
},
dimensions: ['起始日期', '结束日期', 'name'],
encode: {
x: 0,
y: 2,
tooltip: [0, 1, 2],
itemName: 3
},
data: data2
}
]
};
效果:
四、折线图比梯级图多一点
renderItem 实现
option = {
xAxis: {
type: 'category',
data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri'],
boundaryGap:false
},
yAxis: {
type: 'value'
},
series: [
{
data: [150, 230, 224, 218, 135],
type: 'line'
},
{
data: [[15, 23],[23,29], [29,21],[21]],
type: 'custom',
renderItem:function(params,api){
const xIndex = params.dataIndex;
const circleR = 3
// 横线
const horizontalPoint = api.coord([xIndex, api.value(0)]);
// 竖线
const verticalPoint = api.coord([xIndex, api.value(1)]);
const lineWidth = api.size([1, 0])[0];
const halfWidth = lineWidth*0.5;
//
const style = api.style({
stroke: api.visual('color'),
fill: undefined
});
const groupObj ={
type: 'group',
children: [
{
//横线
type: 'line',
shape: {
x1:horizontalPoint[0],
y1:horizontalPoint[1],
x2:horizontalPoint[0]+halfWidth-circleR*0.5,
y2:horizontalPoint[1]
},
style
},
{
//横线
type: 'line',
shape: {
x1:horizontalPoint[0]+halfWidth+circleR*0.5,
y1:horizontalPoint[1],
x2:horizontalPoint[0]+lineWidth,
y2:horizontalPoint[1]
},
style
},
{
//竖线
type: 'line',
shape: {
x1: horizontalPoint[0]+lineWidth,
y1: horizontalPoint[1],
x2: horizontalPoint[0]+lineWidth,
y2: verticalPoint[1]
},
style
},
{
// 小圆点-在横线中间
type: 'circle',
shape: {
cx: horizontalPoint[0]+ halfWidth,
cy: horizontalPoint[1],
r: circleR
},
style
}
]
}
return groupObj
}
},
]
};
带toolTip
option = {
xAxis: {
type: 'category',
data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri'],
boundaryGap:false
},
tooltip:{},
yAxis: {
type: 'value'
},
series: [
{
data: [150, 230, 224, 218, 135],
type: 'line'
},
{
// [15,23,29,21]===> [[15, 23],[23,29], [29,21],[21]]
data: [[23,15],[29,23], [21,29],[21,21]],
type: 'custom',
renderItem:function(params,api){
const xIndex = params.dataIndex;
const circleR = 3
// 横线
const horizontalPoint = api.coord([xIndex, api.value(1)]);
// 竖线
const verticalPoint = api.coord([xIndex, api.value(0)]);
const lineWidth = api.size([1, 0])[0];
const halfWidth = lineWidth*0.5;
//
const style = api.style({
stroke: api.visual('color'),
fill: undefined
});
const groupObj ={
type: 'group',
children: [
{
//横线
type: 'line',
shape: {
x1:horizontalPoint[0],
y1:horizontalPoint[1],
x2:horizontalPoint[0]+halfWidth-circleR*0.5,
y2:horizontalPoint[1]
},
style
},
{
//横线
type: 'line',
shape: {
x1:horizontalPoint[0]+halfWidth+circleR*0.5,
y1:horizontalPoint[1],
x2:horizontalPoint[0]+lineWidth,
y2:horizontalPoint[1]
},
style
},
{
//竖线
type: 'line',
shape: {
x1: horizontalPoint[0]+lineWidth,
y1: horizontalPoint[1],
x2: horizontalPoint[0]+lineWidth,
y2: verticalPoint[1]
},
style
},
{
// 小圆点-在横线中间
type: 'circle',
shape: {
cx: horizontalPoint[0]+ halfWidth,
cy: horizontalPoint[1],
r: circleR
},
style
}
]
}
return groupObj
}
},
]
};
效果:
数据结构优化,不连接Null
// 从第二个点开始画,后往前画
// const yData = [15,123,209,21]
const yData = [null,15,123,209,35]
option = {
tooltip:{
trigger:'axis'
},
xAxis: {
type: 'category',
data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri'],
boundaryGap:false
},
yAxis: {
type: 'value'
},
series: [
{
data: [150, 230, 224, 218, 135],
type: 'line'
},
{
data: yData,
type: 'custom',
tooltip:{},
renderItem:function(params,api){
const xIndex = params.dataIndex;
if(xIndex ===0) return
const circleR = 2.2
// 横线
const horizontalPoint = api.coord([xIndex, api.value(1)]);
// 竖线
const verticalPoint = api.coord([xIndex, yData[xIndex+1]]);
const lineWidth = api.size([1, 0])[0];
//
const style = api.style({
stroke: api.visual('color'),
fill: undefined
});
const groupObj ={
type: 'group',
children: []
}
// 横线
if((api.value(1) || api.value(1) ===0) ){
groupObj.children.push(
{
//横线
type: 'line',
shape: {
x1:horizontalPoint[0] - circleR,
y1:horizontalPoint[1],
x2:horizontalPoint[0] - lineWidth,
y2:horizontalPoint[1]
},
style
},
{
// 小圆点-在横线末端
type: 'circle',
shape: {
cx: horizontalPoint[0],
cy: horizontalPoint[1],
r: circleR
},
style
})
}
// 竖线
if((yData[xIndex+1] || yData[xIndex+1] ===0) ){
groupObj.children.push(
{
type: 'line',
shape: {
x1: horizontalPoint[0],
y1: yData[xIndex+1]>yData[xIndex]?horizontalPoint[1]- circleR:horizontalPoint[1]+ circleR,
x2: horizontalPoint[0],
y2: verticalPoint[1]
},
style
}
)
}
return groupObj
}
},
]
};
五、自定义阶梯图填充颜色
renderItem 实现
// 从第二个点开始画,后往前画
// const yData = [15,123,209,21]
const yData = [null,15,123,209,35]
option = {
tooltip:{
trigger:'axis'
},
xAxis: {
type: 'category',
data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri'],
boundaryGap:false
},
yAxis: {
type: 'value'
},
series: [
{
data: [150, 230, 224, 218, 135],
type: 'line'
},
{
data: yData,
type: 'custom',
tooltip:{},
renderItem:function(params,api){
const xIndex = params.dataIndex;
// if(xIndex ===0) return
const circleR = 2.2
// 横线
const horizontalPoint = api.coord([xIndex, api.value(1)]);
// 竖线
const verticalPoint = api.coord([xIndex, yData[xIndex+1]]);
const lineWidth = api.size([1, 0])[0];
//
const style = api.style({
stroke: api.visual('color'),
fill: undefined,
});
const groupObj ={
type: 'group',
children: []
}
// 横线
if((api.value(1) || api.value(1) ===0) ){
groupObj.children.push(
{
//横线
type: 'line',
shape: {
x1:horizontalPoint[0] - circleR,
y1:horizontalPoint[1],
x2:horizontalPoint[0] - lineWidth,
y2:horizontalPoint[1]
},
style
},
{
// 小圆点-在横线末端
type: 'circle',
shape: {
cx: horizontalPoint[0],
cy: horizontalPoint[1],
r: circleR
},
style
})
}
// 竖线
if((yData[xIndex+1] || yData[xIndex+1] ===0) ){
groupObj.children.push(
{
type: 'line',
// areaStyle: {},
shape: {
x1: horizontalPoint[0],
y1: yData[xIndex+1]>yData[xIndex]?horizontalPoint[1]- circleR:horizontalPoint[1]+ circleR,
x2: horizontalPoint[0],
y2: verticalPoint[1]
},
style
}
)
}
let fillFlag=true
if(fillFlag){
groupObj.children.push(
{
type:'rect',
shape:{
x: horizontalPoint[0],
y: verticalPoint[1],
width:lineWidth,
height:api.size([1, yData[xIndex+1]])[1]
},
style:{
stroke:'red',
lineWidth:0,
fill: api.visual('color')
},
}
)
}
return groupObj
}
},
]
};
效果如下:
小圆点在线段中间的算法
// 横线
if((api.value(1) || api.value(1) ===0) ){
groupObj.children.push(
{
//横线
type: 'line',
shape: {
x1:horizontalPoint[0] - circleR - halfWidth,
y1:horizontalPoint[1],
x2:horizontalPoint[0] - lineWidth,
y2:horizontalPoint[1]
},
style
},
{
// 小圆点-在横线中间
type: 'circle',
shape: {
cx: horizontalPoint[0]- halfWidth,
cy: horizontalPoint[1],
r: circleR
},
style
},
{
//横线
type: 'line',
shape: {
x1:horizontalPoint[0],
y1:horizontalPoint[1],
x2:horizontalPoint[0] - halfWidth +circleR,
y2:horizontalPoint[1]
},
style
},
)
}