218 lines
6.4 KiB
JavaScript
218 lines
6.4 KiB
JavaScript
|
|
/*
|
|
* Licensed to the Apache Software Foundation (ASF) under one
|
|
* or more contributor license agreements. See the NOTICE file
|
|
* distributed with this work for additional information
|
|
* regarding copyright ownership. The ASF licenses this file
|
|
* to you under the Apache License, Version 2.0 (the
|
|
* "License"); you may not use this file except in compliance
|
|
* with the License. You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing,
|
|
* software distributed under the License is distributed on an
|
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
* KIND, either express or implied. See the License for the
|
|
* specific language governing permissions and limitations
|
|
* under the License.
|
|
*/
|
|
|
|
var layout = require("../../util/layout");
|
|
|
|
var _number = require("../../util/number");
|
|
|
|
var parsePercent = _number.parsePercent;
|
|
var linearMap = _number.linearMap;
|
|
|
|
/*
|
|
* Licensed to the Apache Software Foundation (ASF) under one
|
|
* or more contributor license agreements. See the NOTICE file
|
|
* distributed with this work for additional information
|
|
* regarding copyright ownership. The ASF licenses this file
|
|
* to you under the Apache License, Version 2.0 (the
|
|
* "License"); you may not use this file except in compliance
|
|
* with the License. You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing,
|
|
* software distributed under the License is distributed on an
|
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
* KIND, either express or implied. See the License for the
|
|
* specific language governing permissions and limitations
|
|
* under the License.
|
|
*/
|
|
function getViewRect(seriesModel, api) {
|
|
return layout.getLayoutRect(seriesModel.getBoxLayoutParams(), {
|
|
width: api.getWidth(),
|
|
height: api.getHeight()
|
|
});
|
|
}
|
|
|
|
function getSortedIndices(data, sort) {
|
|
var valueDim = data.mapDimension('value');
|
|
var valueArr = data.mapArray(valueDim, function (val) {
|
|
return val;
|
|
});
|
|
var indices = [];
|
|
var isAscending = sort === 'ascending';
|
|
|
|
for (var i = 0, len = data.count(); i < len; i++) {
|
|
indices[i] = i;
|
|
} // Add custom sortable function & none sortable opetion by "options.sort"
|
|
|
|
|
|
if (typeof sort === 'function') {
|
|
indices.sort(sort);
|
|
} else if (sort !== 'none') {
|
|
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');
|
|
var labelPosition = labelModel.get('position');
|
|
var labelLineModel = itemModel.getModel('labelLine');
|
|
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
|
|
};
|
|
});
|
|
}
|
|
|
|
function _default(ecModel, api, payload) {
|
|
ecModel.eachSeriesByType('funnel', function (seriesModel) {
|
|
var data = seriesModel.getData();
|
|
var valueDim = data.mapDimension('value');
|
|
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(valueDim);
|
|
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(valueDim, idx) || 0;
|
|
var itemWidth = 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 itemModel = data.getItemModel(idx);
|
|
var height = itemModel.get('itemStyle.height');
|
|
|
|
if (height == null) {
|
|
height = itemHeight;
|
|
} else {
|
|
height = parsePercent(height, viewRect.height);
|
|
|
|
if (sort === 'ascending') {
|
|
height = -height;
|
|
}
|
|
}
|
|
|
|
var start = getLinePoints(idx, y);
|
|
var end = getLinePoints(nextIdx, y + height);
|
|
y += height + gap;
|
|
data.setItemLayout(idx, {
|
|
points: start.concat(end.slice().reverse())
|
|
});
|
|
}
|
|
|
|
labelLayout(data);
|
|
});
|
|
}
|
|
|
|
module.exports = _default; |