W3Cschool
恭喜您成為首批注冊(cè)用戶
獲得88經(jīng)驗(yàn)值獎(jiǎng)勵(lì)
自定義系列(custom series)是一種系列的類型,它能夠讓用戶定制渲染邏輯,在已有的坐標(biāo)系中創(chuàng)造新的圖表;并且增強(qiáng)了極坐標(biāo)柱狀圖、自定義維度映射、dataZoom 等 。
自定義系列(custom series)它把繪制圖形元素這一步留給開發(fā)者去做,從而開發(fā)者能在坐標(biāo)系中自由繪制出自己需要的圖表。
由于圖表的類型多種多樣,要讓 ECharts 內(nèi)置支持所有類型的圖表是很難的,有很多小眾的需求 ECharts 并不能內(nèi)置的支持。那么就需要提供一種方式來(lái)讓開發(fā)者自己擴(kuò)展。另一方面,所提供的擴(kuò)展方式要盡可能得簡(jiǎn)單,例如圖形元素創(chuàng)建和釋放、過(guò)渡動(dòng)畫、tooltip、數(shù)據(jù)區(qū)域縮放(dataZoom)、視覺(jué)映射(visualMap)等功能,盡量在 ECharts 中內(nèi)置得處理,使開發(fā)者不必糾結(jié)于這些細(xì)節(jié)。綜上考慮形成了 自定義系列(custom series)。
例如,下面的例子使用自定義系列( custom series)擴(kuò)展出了 x-range 圖:
下面來(lái)介紹開發(fā)者怎么使用自定義系列(custom series)。
通過(guò)書寫 renderItem 函數(shù)能夠讓開發(fā)者實(shí)現(xiàn)自定義的圖形元素渲染邏輯,例如:
var option = {
...,
series: [{
type: 'custom',
renderItem: function (params, api) {
// ...
},
data: data
}]
}
在渲染階段,對(duì)于 series.data 中的每個(gè)數(shù)據(jù)項(xiàng)(為方便描述,這里稱為 dataItem),會(huì)調(diào)用此 renderItem 函數(shù)。
renderItem 函數(shù)的作用:返回一個(gè)(或者一組)圖形元素定義,圖形元素定義了圖形元素的類型、位置、尺寸、樣式等。
ECharts 會(huì)根據(jù)這些 圖形元素定義 來(lái)渲染出圖形元素。如下述所示:
var option = {
...,
series: [{
type: 'custom',
renderItem: function (params, api) {
// 對(duì)于 data 中的每個(gè) dataItem,都會(huì)調(diào)用這個(gè) renderItem 函數(shù)。
// (但是注意,并不一定是按照 data 的順序調(diào)用)
// 這里進(jìn)行一些處理,例如,坐標(biāo)轉(zhuǎn)換。
// 這里使用 api.value(0) 取出當(dāng)前 dataItem 中第一個(gè)維度的數(shù)值。
var categoryIndex = api.value(0);
// 這里使用 api.coord(...) 將數(shù)值在當(dāng)前坐標(biāo)系中轉(zhuǎn)換成為屏幕上的點(diǎn)的像素值。
var startPoint = api.coord([api.value(1), categoryIndex]);
var endPoint = api.coord([api.value(2), categoryIndex]);
// 這里使用 api.size(...) 獲得 Y 軸上數(shù)值范圍為 1 的一段所對(duì)應(yīng)的像素長(zhǎng)度。
var height = api.size([0, 1])[1] * 0.6;
// 這里返回為這個(gè) dataItem 構(gòu)建的圖形元素定義。
return {
// 表示這個(gè)圖形元素是矩形。還可以是 'circle', 'sector', 'polygon' 等等。
type: 'rect',
// shape 屬性描述了這個(gè)矩形的像素位置和大小。
// 其中特殊得用到了 echarts.graphic.clipRectByRect,意思是,
// 如果矩形超出了當(dāng)前坐標(biāo)系的包圍盒,則剪裁這個(gè)矩形。
shape: echarts.graphic.clipRectByRect({
// 矩形的位置和大小。
x: startPoint[0],
y: startPoint[1] - height / 2,
width: endPoint[0] - startPoint[0],
height: height
}, {
// 當(dāng)前坐標(biāo)系的包圍盒。
x: params.coordSys.x,
y: params.coordSys.y,
width: params.coordSys.width,
height: params.coordSys.height
}),
// 用 api.style(...) 得到默認(rèn)的樣式設(shè)置。這個(gè)樣式設(shè)置包含了
// option 中 itemStyle 的配置和視覺(jué)映射得到的顏色。
style: api.style()
};
},
data: [
[12, 44, 55, 60], // 這是第一個(gè) dataItem
[53, 31, 21, 56], // 這是第二個(gè) dataItem
[71, 33, 10, 20], // 這是第三個(gè) dataItem
...
]
}]
}
renderItem 函數(shù)中包含兩個(gè)參數(shù):
renderItem 函數(shù)須返回根據(jù)此 dataItem 繪制出的圖形元素的定義信息,參見(jiàn) renderItem.return。
一般來(lái)說(shuō),renderItem 函數(shù)的主要邏輯,是將 dataItem 里的值映射到坐標(biāo)系上的圖形元素。這一般需要用到 renderItem.arguments.api 中的兩個(gè)函數(shù):
有時(shí)候還需要用到 api.size(...) 函數(shù),表示得到坐標(biāo)系上一段數(shù)值范圍對(duì)應(yīng)的長(zhǎng)度。
返回值中樣式的設(shè)置可以使用 api.style(...) 函數(shù),他能得到 series.itemStyle.normal 中定義的樣式信息,以及視覺(jué)映射的樣式信息。也可以用這種方式覆蓋這些樣式信息:api.style({fill: 'green', stroke: 'yellow'})。
renderItem 方法寫完后,我們就完成了自定義系列 90% 的工作,接下來(lái)該對(duì)工作進(jìn)行優(yōu)化了。
直角坐標(biāo)系(grid)和極坐標(biāo)系(polar)中的坐標(biāo)軸的刻度范圍需要自適應(yīng)當(dāng)前顯示出的數(shù)據(jù)的范圍,否則繪制出的圖形會(huì)超出去。
例如,在直角坐標(biāo)系(grid)中,開發(fā)者如果使用自定義系列的話,就需要設(shè)定,data 中的哪些維度會(huì)對(duì)應(yīng)到 x 軸上,哪些維度會(huì)對(duì)應(yīng)到 y 軸上。
上述內(nèi)容通過(guò) encode 來(lái)設(shè)定。例如:
option = {
series: [{
type: 'custom',
renderItem: function () {
...
},
encode: {
// data 中『維度1』和『維度2』對(duì)應(yīng)到 X 軸
x: [1, 2],
// data 中『維度0』對(duì)應(yīng)到 Y 軸
y: 0
},
data: [
// 維度0 維度1 維度2 維度3
[ 12, 44, 55, 60 ], // 這是第一個(gè) dataItem
[ 53, 31, 21, 56 ], // 這是第二個(gè) dataItem
[ 71, 33, 10, 20 ], // 這是第三個(gè) dataItem
...
]
}]
};
當(dāng)然,使用 tooltip.formatter 可以任意定制 tooltip 中的內(nèi)容。
但是,還有更簡(jiǎn)單的方法,即通過(guò) encode 和 dimensions 來(lái)設(shè)定:
option = {
series: [{
type: 'custom',
renderItem: function () {
...
},
encode: {
x: [1, 2],
y: 0,
// 表示『維度2』和『維度3』要顯示到 tooltip 中。
tooltip: [2, 3]
},
// 表示給『維度2』和『維度3』分別取名為『年齡』和『滿意度』,顯示到 tooltip 中。
dimensions: [null, null, '年齡', '滿意度'],
data: [
// 維度0 維度1 維度2 維度3
[ 12, 44, 55, 60 ], // 這是第一個(gè) dataItem
[ 53, 31, 21, 56 ], // 這是第二個(gè) dataItem
[ 71, 33, 10, 20 ], // 這是第三個(gè) dataItem
...
]
}]
};
(1)與 dataZoom 結(jié)合使用的時(shí)候,常常使用會(huì)設(shè)置 dataZoom.filterMode 為 'weakFilter'。這個(gè)設(shè)置的意思是:當(dāng) dataItem 部分超出坐標(biāo)系邊界的時(shí)候,dataItem 不會(huì)整體被過(guò)濾掉。例如:
option = {
dataZoom: {
xAxisIndex: 0,
filterMode: 'weakFilter'
},
series: [{
type: 'custom',
renderItem: function () {
...
},
encode: {
// data 中『維度1』和『維度2』對(duì)應(yīng)到 X 軸
x: [1, 2],
y: 0
},
data: [
// 維度0 維度1 維度2 維度3
[ 12, 44, 55, 60 ], // 這是第一個(gè) dataItem
[ 53, 31, 21, 56 ], // 這是第二個(gè) dataItem
[ 71, 33, 10, 20 ], // 這是第三個(gè) dataItem
...
]
}]
};
在上述例子中,維度1和維度2對(duì)應(yīng)到 X 軸,dataZoom 組件控制 X 軸的縮放。
假如在縮放的過(guò)程中,某個(gè) dataItem 的維度1超出了 X 軸的范圍,維度2還在 X 軸的范圍中,那么只要設(shè)置 dataZoom.filterMode = 'weakFilter',這個(gè) dataItem 就不會(huì)被過(guò)濾掉,從而還能夠使用 renderItem 繪制圖形(可以使用上面提到過(guò)的 echarts.graphic.clipRectByRect 把圖形繪制成被坐標(biāo)系剪裁過(guò)的樣子)。參見(jiàn)上面提到過(guò)的例子:Profile
(2)此外,開發(fā)者還應(yīng)注意,renderItem.arguments.params 中的 dataIndex 和 dataIndexInside 是有區(qū)別的:
renderItem.arguments.api 中使用的參數(shù)都是 dataIndexInside 而非 dataIndex,因?yàn)閺?nbsp;dataIndex 轉(zhuǎn)換成 dataIndexInside 需要時(shí)間開銷。
更多的自定義系列的例子參見(jiàn):custom examples
Copyright©2021 w3cschool編程獅|閩ICP備15016281號(hào)-3|閩公網(wǎng)安備35020302033924號(hào)
違法和不良信息舉報(bào)電話:173-0602-2364|舉報(bào)郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號(hào)
聯(lián)系方式:
更多建議: