對菜鳥來說,這真的是一個深坑……
先說結局:
1、params對象的成員在echarts的“配置項”說明(http://echarts.baidu.com/option.html#series-bar.tooltip.formatter)裏進行了介紹,但並沒有出現seriesId成員;
2、以3.5.0版本爲例,seriesId最終是由3865行的keyInfo.id ='\0' + keyInfo.name + '\0' + idNum++; 生成的,因此,你總會發現seriesId明明是個字符串,長度seriesId.length卻總是不對;
3、本文意在bar series tooltip的formatter中獲取bar的stack值(http://echarts.baidu.com/option.html#series-bar.stack),echarts3.5.0、3.6.1中均未在params對象中提供。本文最終對echarts-3.5.0.js文件的getDataParams方法進行了修改,以便獲取到stack參數,以3.5.0版本爲例,第3618行開始,整個方法最終如下(其實就增加了一行):
getDataParams: function (dataIndex, dataType) {
var data = this.getData(dataType);
var rawValue = this.getRawValue(dataIndex, dataType);
var rawDataIndex = data.getRawIndex(dataIndex);
var name = data.getName(dataIndex, true);
var itemOpt = data.getRawDataItem(dataIndex);
return {
componentType: this.mainType,
componentSubType: this.subType,
seriesType: this.mainType === 'series' ? this.subType : null,
seriesIndex: this.seriesIndex,
seriesId: this.id,
seriesName: this.name,
name: name,
dataIndex: rawDataIndex,
data: itemOpt,
dataType: dataType,
value: rawValue,
color: data.getItemVisual(dataIndex, 'color'),
stack: this.get(‘stack’), //增加此行,修改之處
// Param name list for mapping `a`, `b`, `c`, `d`, `e`
$vars: ['seriesName', 'name', 'value']
};
},
羅索的正文:
本文針對的echarts版本爲:3.5.0;3.6.1;
使用echarts,作者期望初步得到下面的結果圖:
並且,在上圖中,能實現這樣的效果:舉例來說,當鼠標hover到“產品1”的“口徑1”最上面的棕色區域時,在彈出的tooltip中應該顯示中關鍵字“口徑1”、“產品1”、“8類買家”等。
但是,從上圖的tooltip中,能夠看到,並沒有“口徑1”的字眼……
如何獲取?
從echarts的文檔http://echarts.baidu.com/option.html#series-bar.stack處,我們能夠看到stack的介紹,它主要起數據堆疊的作用。但尷尬的是,我通過你堆疊之後,卻不能知道我的堆疊的組是誰。
所以,作者仔細觀察tooltip的顯示,發現seriesId的值“8類買家0”(如上圖tooltip內),與seriesName的值“8類買家”就差一個0,而且,當移動到“口徑2”時,這個“8類買家0”會變爲“8類買家1”。想當然的,作者以爲這個0、1至少能夠代表stack的索引吧。
然後就開始瞭如下的代碼:
tooltip : {
formatter: function(params) {
var iStackIndex = parseInt(params.seriesId.replace(params.seriesName, ''));
return aryStack[iStackIndex];
}
},
然後發現,iStackIndex總是爲NaN,百思不得其解,各種查看文檔各種找資料,玩兒命懷疑智商……
然而,茫然堅守的調試仍舊沒有解決問題。
然後使用console.log(params.seriesId.length)發現其長度總是不對,而同樣的console.log(params.seriesName.length)卻是對的。
經過#%.^&^@的折騰,最後,終於跟同事一起構造出了seriesId裏面莫名出現的’\0’。作爲前端小白,真心覺得WTF……
後面的事兒就簡單了,搜索echarts的源碼,發現真有’\0’出現,然後再一點點回溯,終於發現了本文開頭結局中的第2點。
並且發現了上面的0、1與stack的索引僅是巧合,根本不能用其代表自己構造的stack數組下標。
最後,附上上文echarts圖的源碼,以便讓你知道我在說什麼:
(注意,你需要在http://echarts.baidu.com/demo.html#bar-stack運行下面的代碼)
app.title = '堆疊柱狀圖';
// 生成n個和爲sum的隨機整數
function randGenerator(n, sum) {
var aryRet = [];
var fSumTmp = sum;
var iAcc = 0;
for (var i = 0; i < (n -1); i++) {
var iTmp = Math.ceil(Math.random() * (fSumTmp / 2));
aryRet.push(iTmp);
fSumTmp -= iTmp;
iAcc += iTmp;
}
aryRet.push(sum-iAcc);
return aryRet;
}
var aryDataXAxis = ['產品A','產品B','產品C','產品D','產品E'];
var aryDataLegend = ['1類買家','2類買家','3類買家','4類買家','5類買家','6類買家','8類買家'];
// map的格式
// mapData = ['口徑1', '口徑2']['產品A','產品B','產品C','產品D','產品E']['1類買家','2類買家','3類買家','4類買家','5類買家','6類買家','8類買家']
var mapData = [];
mapData['口徑1'] = [];
mapData['口徑2'] = [];
var aryStack = [];
// 最外層標明“口徑1”、“口徑2”
for (var itemMap in mapData) {
aryStack.push(itemMap);
// x軸
for (var itemXAxis in aryDataXAxis) {
mapData[itemMap][itemXAxis] = [];
// y軸
// for (var itemLegend in aryDataLegend) {
// mapData[itemMap][itemXAxis].push((Math.random() * 100).toFixed(1));
// }
mapData[itemMap][itemXAxis] = randGenerator(aryDataLegend.length, 100);
}
}
var arySeries = [];
// 最外層標明“口徑1”、“口徑2”
for (var itemMap in mapData) {
// y軸
for (var itemLegend in aryDataLegend) {
//console.log(aryDataLegend[itemLegend]);
var objTmp = new Object();
objTmp.name = aryDataLegend[itemLegend];
objTmp.type = 'bar';
objTmp.stack = itemMap;
objTmp.data = [];
// x軸
for (var itemXAxis in aryDataXAxis) {
objTmp.data.push(mapData[itemMap][itemXAxis][itemLegend]);
}
objTmp.tooltip = {
formatter: function (params) {
return funcTooltip(params);
}
};
if (itemLegend == aryDataLegend.length - 1) {
objTmp.label = {
normal: {
show: true,
position: 'top',
textStyle: {
color: '#666'
},
formatter: itemMap
}
};
}
arySeries.push(objTmp);
}
}
function funcTooltip(params) {
var aryHtml = [];
aryHtml.push('<div style="text-align:left;">');
for (var item in params) {
aryHtml.push('<br />');
aryHtml.push(item + ':' + params[item]);
}
aryHtml.push('</div>');
return aryHtml.join('');
}
option = {
tooltip : {
formatter: function(params) {
var iStackIndex = parseInt(params.seriesId.replace(params.seriesName, ''));
return aryStack[iStackIndex];
}
},
legend: {
data: aryDataLegend
},
grid: {
left: '3%',
right: '4%',
height: '280',
containLabel: true
},
xAxis : [
{
type : 'category',
data : aryDataXAxis
}
],
yAxis : [
{
type : 'value'
}
],
series : arySeries
};