define(function (require) {
var layout = require('../../util/layout');
var number = require('../../util/number');
var parsePercent = number.parsePercent;
function getViewRect(seriesModel, api) {
return layout.getLayoutRect(
seriesModel.getBoxLayoutParams(), {
width: api.getWidth(),
height: api.getHeight()
}
);
}
function getSortedIndices(data, sort) {
var valueArr = data.mapArray('value', function (val) {
return val;
});
var indices = [];
var isAscending = sort === 'ascending';
for (var i = 0, len = data.count(); i < len; i++) {
indices[i] = i;
}
indices.sort(function (a, b) {
return isAscending ? valueArr[a] - valueArr[b] : valueArr[b] - valueArr[a];
});
return indices;
}
function labelLayout (data) {
data.each(function (idx) {
var itemModel = data.getItemModel(idx);
var labelModel = itemModel.getModel('label.normal');
var labelPosition = labelModel.get('position');
var labelLineModel = itemModel.getModel('labelLine.normal');
var layout = data.getItemLayout(idx);
var points = layout.points;
var isLabelInside = labelPosition === 'inner'
|| labelPosition === 'inside' || labelPosition === 'center';
var textAlign;
var textX;
var textY;
var linePoints;
if (isLabelInside) {
textX = (points[0][0] + points[1][0] + points[2][0] + points[3][0]) / 4;
textY = (points[0][1] + points[1][1] + points[2][1] + points[3][1]) / 4;
textAlign = 'center';
linePoints = [
[textX, textY], [textX, textY]
];
}
else {
var x1;
var y1;
var x2;
var labelLineLen = labelLineModel.get('length');
if (labelPosition === 'left') {
// Left side
x1 = (points[3][0] + points[0][0]) / 2;
y1 = (points[3][1] + points[0][1]) / 2;
x2 = x1 - labelLineLen;
textX = x2 - 5;
textAlign = 'right';
}
else {
// Right side
x1 = (points[1][0] + points[2][0]) / 2;
y1 = (points[1][1] + points[2][1]) / 2;
x2 = x1 + labelLineLen;
textX = x2 + 5;
textAlign = 'left';
}
var y2 = y1;
linePoints = [[x1, y1], [x2, y2]];
textY = y2;
}
layout.label = {
linePoints: linePoints,
x: textX,
y: textY,
verticalAlign: 'middle',
textAlign: textAlign,
inside: isLabelInside
};
});
}
return function (ecModel, api) {
ecModel.eachSeriesByType('funnel', function (seriesModel) {
var data = seriesModel.getData();
var sort = seriesModel.get('sort');
var viewRect = getViewRect(seriesModel, api);
var indices = getSortedIndices(data, sort);
var sizeExtent = [
parsePercent(seriesModel.get('minSize'), viewRect.width),
parsePercent(seriesModel.get('maxSize'), viewRect.width)
];
var dataExtent = data.getDataExtent('value');
var min = seriesModel.get('min');
var max = seriesModel.get('max');
if (min == null) {
min = Math.min(dataExtent[0], 0);
}
if (max == null) {
max = dataExtent[1];
}
var funnelAlign = seriesModel.get('funnelAlign');
var gap = seriesModel.get('gap');
var itemHeight = (viewRect.height - gap * (data.count() - 1)) / data.count();
var y = viewRect.y;
var getLinePoints = function (idx, offY) {
// End point index is data.count() and we assign it 0
var val = data.get('value', idx) || 0;
var itemWidth = number.linearMap(val, [min, max], sizeExtent, true);
var x0;
switch (funnelAlign) {
case 'left':
x0 = viewRect.x;
break;
case 'center':
x0 = viewRect.x + (viewRect.width - itemWidth) / 2;
break;
case 'right':
x0 = viewRect.x + viewRect.width - itemWidth;
break;
}
return [
[x0, offY],
[x0 + itemWidth, offY]
];
};
if (sort === 'ascending') {
// From bottom to top
itemHeight = -itemHeight;
gap = -gap;
y += viewRect.height;
indices = indices.reverse();
}
for (var i = 0; i < indices.length; i++) {
var idx = indices[i];
var nextIdx = indices[i + 1];
var start = getLinePoints(idx, y);
var end = getLinePoints(nextIdx, y + itemHeight);
y += itemHeight + gap;
data.setItemLayout(idx, {
points: start.concat(end.slice().reverse())
});
}
labelLayout(data);
});
};
});
|