1、配置series
data: [
维度0 维度1 维度2 维度3
[ 12, 44, 55, 60 ], 这是第一个 dataItem
[ 53, 31, 21, 56 ], 这是第二个 dataItem
[ 71, 33, 10, 20 ], 这是第三个 dataItem
...
]
series:[{
type:'custom',
renderItem: function (params, api) {
(1)params包含了当前数据信息和坐标系的信息。
context: // {Object} 一个可供开发者暂存东西的对象。生命周期只为:当前次的渲染。
seriesId: // {string} 本系列 id。
seriesName: // {string} 本系列 name。
seriesIndex: // {number} 本系列 index。
dataIndex: // {number} 数据项的 index。
dataIndexInside: // {number} 数据项在当前坐标系中可见的数据的 index(即 dataZoom 当前窗口中的数据的 index)。
dataInsideLength: // {number} 当前坐标系中可见的数据长度(即 dataZoom 当前窗口中的数据数量)。
actionType: // {string} 触发此次重绘的 action 的 type。
coordSys: // 不同的坐标系中,coordSys 里的信息不一样,含有如下这些可能:
coordSys: {
type: 'cartesian2d',
x: // {number} grid rect 的 x
y: // {number} grid rect 的 y
width: // {number} grid rect 的 width
height: // {number} grid rect 的 height
},
coordSys: {
type: 'calendar',
x: // {number} calendar rect 的 x
y: // {number} calendar rect 的 y
width: // {number} calendar rect 的 width
height: // {number} calendar rect 的 height
cellWidth: // {number} calendar cellWidth
cellHeight: // {number} calendar cellHeight
rangeInfo: {
start: // calendar 日期开端
end: // calendar 日期结尾
weeks: // calendar 周数
dayCount: // calendar 日数
}
},
coordSys: {
type: 'geo',
x: // {number} geo rect 的 x
y: // {number} geo rect 的 y
width: // {number} geo rect 的 width
height: // {number} geo rect 的 height
zoom: // {number} 缩放的比率。如果没有缩放,则值为 1。例如 0.5 表示缩小了一半。
},
coordSys: {
type: 'polar',
cx: // {number} polar 的中心坐标
cy: // {number} polar 的中心坐标
r: // {number} polar 的外半径
r0: // {number} polar 的内半径
},
coordSys: {
type: 'singleAxis',
x: // {number} singleAxis rect 的 x
y: // {number} singleAxis rect 的 y
width: // {number} singleAxis rect 的 width
height: // {number} singleAxis rect 的 height
}
(2)api开发者可调用的方法集合
api.value(),意思是取出dataItem中的数值,api.value(0)表示取出当前 dataItem 中第一个维度的数值。
api.coord(),意思是进行坐标转换计算,var point = api.coord([api.value(0), api.value(1)]) 表示 dataItem 中的数值转换成坐标系上的点。
api.size() 意思是得到坐标系上一段数值范围对应的长度,api.size([2, 4])返回[12.4, 55],表示x轴数据范围为2映射得到长度是12.4,y轴数据范围为4时得到长度为55
api.style() 意思是得到series.itemStyle中定义的样式信息,以及视觉映射的样式信息,也可以用这种方式覆盖这些样式信息:api.style({fill: 'green', stroke: 'yellow'})
api.barLayout() 意思是得到柱状的布局信息或覆盖api.barLayout({barGap: '30%'})
api.visual() 得到视觉映射的样式信息, api.visual('color')
...
},
data,
encode:{},
...
}]
2、根据renderItem返回的内容绘制自定义图表
renderItem(params,api){
(1)从dataItem中得到需要的数据
api.value(n)
...
(2)根据数据转换成坐标系中的坐标点
api.coord([x,y])
(3)根据数据获得一些坐标系中的长度
api.size([2, 4])返回[12.4, 55], 表示x轴数据索引为2映射得到长度是12.4,y轴数据索引为4时得到长度为55
(4)根据选择的图表,进行图表的样式定制
var style = api.style({
...
});
(4)根据获取到的坐标等信息进行图表的绘制
1.单独一个图形
return {
type: 'rect',
shape: {
x: x, y: y, width: width, height: height
},
style: api.style()
}
2.一组图形元素
return
{
type: 'group',
children: [{
type: 'circle',
shape: {
cx: cx, cy: cy, r: r
},
style: api.style()
}, {
type: 'line',
shape: {
x1: x1, y1: y1, x2: x2, y2: y2
},
style: api.style()
}]
}
(5)绘制过程
会根据变量data的每一项,然后每一项数据通过renderItem来进行渲染成图像
}
效果图:
代码示例:
图一:
var categoryData = [];
var errorData = [];
var barData = [];
var dataCount = 100;
for (var i = 0; i < dataCount; i++) {
var val = Math.random() * 1000;
categoryData.push('category' + i);
errorData.push([
i,
echarts.number.round(Math.max(0, val - Math.random() * 100)),
echarts.number.round(val + Math.random() * 80)
]);
barData.push(echarts.number.round(val, 2));
}
//自定义图表errorData数据格式
//0: (3) [0, 605.1815292057, 679.8030379497]
//1: (3) [1, 920.7723004698, 962.3312395196]
//2: (3) [2, 149.3935443747, 171.9616042264]
//3: (3) [3, 165.3770327076, 215.6546992705]
//4: (3) [4, 689.381740467, 802.6794791582]
function renderItem(params, api) {
var xValue = api.value(0);
var lowPoint = api.coord([xValue, api.value(1)]); //得到下面线的中心坐标
var highPoint = api.coord([xValue, api.value(2)]); //得到上面线的中心坐标
var halfWidth = api.size([1, 0])[0] * 0.1; //根据x轴索引为1的数值得到所在的映射宽度*0.1
var style = api.style({
stroke: api.visual('color'),
fill: null
});
return {
type: 'group', //上面那条线
children: [{
type: 'line',
transition: ['shape'],
shape: {
x1: highPoint[0] - halfWidth, y1: highPoint[1],
x2: highPoint[0] + halfWidth, y2: highPoint[1]
},
style: style
}, { //中间垂直线
type: 'line',
transition: ['shape'],
shape: {
x1: highPoint[0], y1: highPoint[1],
x2: lowPoint[0], y2: lowPoint[1]
},
style: style
}, { //下面那条线
type: 'line',
transition: ['shape'],
shape: {
x1: lowPoint[0] - halfWidth, y1: lowPoint[1],
x2: lowPoint[0] + halfWidth, y2: lowPoint[1]
},
style: style
}]
};
}
option = {
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'shadow'
}
},
title: {
text: 'Error bar chart'
},
legend: {
data: ['bar', 'error']
},
dataZoom: [{
type: 'slider',
start: 50,
end: 70
}, {
type: 'inside',
start: 50,
end: 70
}],
xAxis: {
data: categoryData
},
yAxis: {},
series: [{
type: 'bar',
name: 'bar',
data: barData,
itemStyle: {
color: '#77bef7'
}
}, {
type: 'custom',
name: 'error',
itemStyle: {
normal: {
borderWidth: 1.5
}
},
renderItem: renderItem,
encode: {
x: 0,
y: [1, 2]
},
data: errorData,
z: 100
}]
};
图二:
var data = [[10, 16, 3, 'A'], [16, 18, 15, 'B'], [18, 26, 12, 'C'], [26, 32, 22, 'D'], [32, 56, 7, 'E'], [56, 62, 17, 'F']];
var colorList = ['#4f81bd', '#c0504d', '#9bbb59', '#604a7b', '#948a54', '#e46c0b'];
data = data.map(function (item, index) {
return {
value: item,
itemStyle: {
color: colorList[index]
}
};
});
function renderItem(params, api) {
var yValue = api.value(2); //第三项数据为y轴数值
var start = api.coord([api.value(0), yValue]); //转换成在坐标轴中的坐标
var size = api.size([api.value(1) - api.value(0), yValue]); //获取对应数值在坐标系中的长度
var style = api.style();
return {
type: 'rect',
shape: {
x: start[0],
y: start[1],
width: size[0],
height: size[1]
},
style: style
};
}
option = {
title: {
text: 'Profit',
left: 'center'
},
tooltip: {
},
xAxis: {
scale: true
},
yAxis: {
},
series: [{
type: 'custom',
renderItem: renderItem,
label: {
show: true,
position: 'top'
},
dimensions: ['from', 'to', 'profit'],
encode: {
x: [0, 1],
y: 2,
tooltip: [0, 1, 2], //映射到提示框中的维度
itemName: 3
},
data: data
}]
};