282 lines
9.9 KiB
282 lines
9.9 KiB
|
|
/* |
|
* 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. |
|
*/ |
|
|
|
|
|
/** |
|
* AUTO-GENERATED FILE. DO NOT MODIFY. |
|
*/ |
|
|
|
/* |
|
* 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. |
|
*/ |
|
import * as zrUtil from 'zrender/lib/core/util.js'; |
|
import { parsePercent } from '../util/number.js'; |
|
import { isDimensionStacked } from '../data/helper/dataStackHelper.js'; |
|
|
|
function getSeriesStackId(seriesModel) { |
|
return seriesModel.get('stack') || '__ec_stack_' + seriesModel.seriesIndex; |
|
} |
|
|
|
function getAxisKey(polar, axis) { |
|
return axis.dim + polar.model.componentIndex; |
|
} |
|
|
|
function barLayoutPolar(seriesType, ecModel, api) { |
|
var lastStackCoords = {}; |
|
var barWidthAndOffset = calRadialBar(zrUtil.filter(ecModel.getSeriesByType(seriesType), function (seriesModel) { |
|
return !ecModel.isSeriesFiltered(seriesModel) && seriesModel.coordinateSystem && seriesModel.coordinateSystem.type === 'polar'; |
|
})); |
|
ecModel.eachSeriesByType(seriesType, function (seriesModel) { |
|
// Check series coordinate, do layout for polar only |
|
if (seriesModel.coordinateSystem.type !== 'polar') { |
|
return; |
|
} |
|
|
|
var data = seriesModel.getData(); |
|
var polar = seriesModel.coordinateSystem; |
|
var baseAxis = polar.getBaseAxis(); |
|
var axisKey = getAxisKey(polar, baseAxis); |
|
var stackId = getSeriesStackId(seriesModel); |
|
var columnLayoutInfo = barWidthAndOffset[axisKey][stackId]; |
|
var columnOffset = columnLayoutInfo.offset; |
|
var columnWidth = columnLayoutInfo.width; |
|
var valueAxis = polar.getOtherAxis(baseAxis); |
|
var cx = seriesModel.coordinateSystem.cx; |
|
var cy = seriesModel.coordinateSystem.cy; |
|
var barMinHeight = seriesModel.get('barMinHeight') || 0; |
|
var barMinAngle = seriesModel.get('barMinAngle') || 0; |
|
lastStackCoords[stackId] = lastStackCoords[stackId] || []; |
|
var valueDim = data.mapDimension(valueAxis.dim); |
|
var baseDim = data.mapDimension(baseAxis.dim); |
|
var stacked = isDimensionStacked(data, valueDim |
|
/* , baseDim */ |
|
); |
|
var clampLayout = baseAxis.dim !== 'radius' || !seriesModel.get('roundCap', true); |
|
var valueAxisStart = valueAxis.dataToCoord(0); |
|
|
|
for (var idx = 0, len = data.count(); idx < len; idx++) { |
|
var value = data.get(valueDim, idx); |
|
var baseValue = data.get(baseDim, idx); |
|
var sign = value >= 0 ? 'p' : 'n'; |
|
var baseCoord = valueAxisStart; // Because of the barMinHeight, we can not use the value in |
|
// stackResultDimension directly. |
|
// Only ordinal axis can be stacked. |
|
|
|
if (stacked) { |
|
if (!lastStackCoords[stackId][baseValue]) { |
|
lastStackCoords[stackId][baseValue] = { |
|
p: valueAxisStart, |
|
n: valueAxisStart // Negative stack |
|
|
|
}; |
|
} // Should also consider #4243 |
|
|
|
|
|
baseCoord = lastStackCoords[stackId][baseValue][sign]; |
|
} |
|
|
|
var r0 = void 0; |
|
var r = void 0; |
|
var startAngle = void 0; |
|
var endAngle = void 0; // radial sector |
|
|
|
if (valueAxis.dim === 'radius') { |
|
var radiusSpan = valueAxis.dataToCoord(value) - valueAxisStart; |
|
var angle = baseAxis.dataToCoord(baseValue); |
|
|
|
if (Math.abs(radiusSpan) < barMinHeight) { |
|
radiusSpan = (radiusSpan < 0 ? -1 : 1) * barMinHeight; |
|
} |
|
|
|
r0 = baseCoord; |
|
r = baseCoord + radiusSpan; |
|
startAngle = angle - columnOffset; |
|
endAngle = startAngle - columnWidth; |
|
stacked && (lastStackCoords[stackId][baseValue][sign] = r); |
|
} // tangential sector |
|
else { |
|
var angleSpan = valueAxis.dataToCoord(value, clampLayout) - valueAxisStart; |
|
var radius = baseAxis.dataToCoord(baseValue); |
|
|
|
if (Math.abs(angleSpan) < barMinAngle) { |
|
angleSpan = (angleSpan < 0 ? -1 : 1) * barMinAngle; |
|
} |
|
|
|
r0 = radius + columnOffset; |
|
r = r0 + columnWidth; |
|
startAngle = baseCoord; |
|
endAngle = baseCoord + angleSpan; // if the previous stack is at the end of the ring, |
|
// add a round to differentiate it from origin |
|
// let extent = angleAxis.getExtent(); |
|
// let stackCoord = angle; |
|
// if (stackCoord === extent[0] && value > 0) { |
|
// stackCoord = extent[1]; |
|
// } |
|
// else if (stackCoord === extent[1] && value < 0) { |
|
// stackCoord = extent[0]; |
|
// } |
|
|
|
stacked && (lastStackCoords[stackId][baseValue][sign] = endAngle); |
|
} |
|
|
|
data.setItemLayout(idx, { |
|
cx: cx, |
|
cy: cy, |
|
r0: r0, |
|
r: r, |
|
// Consider that positive angle is anti-clockwise, |
|
// while positive radian of sector is clockwise |
|
startAngle: -startAngle * Math.PI / 180, |
|
endAngle: -endAngle * Math.PI / 180, |
|
|
|
/** |
|
* Keep the same logic with bar in catesion: use end value to |
|
* control direction. Notice that if clockwise is true (by |
|
* default), the sector will always draw clockwisely, no matter |
|
* whether endAngle is greater or less than startAngle. |
|
*/ |
|
clockwise: startAngle >= endAngle |
|
}); |
|
} |
|
}); |
|
} |
|
/** |
|
* Calculate bar width and offset for radial bar charts |
|
*/ |
|
|
|
|
|
function calRadialBar(barSeries) { |
|
// Columns info on each category axis. Key is polar name |
|
var columnsMap = {}; |
|
zrUtil.each(barSeries, function (seriesModel, idx) { |
|
var data = seriesModel.getData(); |
|
var polar = seriesModel.coordinateSystem; |
|
var baseAxis = polar.getBaseAxis(); |
|
var axisKey = getAxisKey(polar, baseAxis); |
|
var axisExtent = baseAxis.getExtent(); |
|
var bandWidth = baseAxis.type === 'category' ? baseAxis.getBandWidth() : Math.abs(axisExtent[1] - axisExtent[0]) / data.count(); |
|
var columnsOnAxis = columnsMap[axisKey] || { |
|
bandWidth: bandWidth, |
|
remainedWidth: bandWidth, |
|
autoWidthCount: 0, |
|
categoryGap: '20%', |
|
gap: '30%', |
|
stacks: {} |
|
}; |
|
var stacks = columnsOnAxis.stacks; |
|
columnsMap[axisKey] = columnsOnAxis; |
|
var stackId = getSeriesStackId(seriesModel); |
|
|
|
if (!stacks[stackId]) { |
|
columnsOnAxis.autoWidthCount++; |
|
} |
|
|
|
stacks[stackId] = stacks[stackId] || { |
|
width: 0, |
|
maxWidth: 0 |
|
}; |
|
var barWidth = parsePercent(seriesModel.get('barWidth'), bandWidth); |
|
var barMaxWidth = parsePercent(seriesModel.get('barMaxWidth'), bandWidth); |
|
var barGap = seriesModel.get('barGap'); |
|
var barCategoryGap = seriesModel.get('barCategoryGap'); |
|
|
|
if (barWidth && !stacks[stackId].width) { |
|
barWidth = Math.min(columnsOnAxis.remainedWidth, barWidth); |
|
stacks[stackId].width = barWidth; |
|
columnsOnAxis.remainedWidth -= barWidth; |
|
} |
|
|
|
barMaxWidth && (stacks[stackId].maxWidth = barMaxWidth); |
|
barGap != null && (columnsOnAxis.gap = barGap); |
|
barCategoryGap != null && (columnsOnAxis.categoryGap = barCategoryGap); |
|
}); |
|
var result = {}; |
|
zrUtil.each(columnsMap, function (columnsOnAxis, coordSysName) { |
|
result[coordSysName] = {}; |
|
var stacks = columnsOnAxis.stacks; |
|
var bandWidth = columnsOnAxis.bandWidth; |
|
var categoryGap = parsePercent(columnsOnAxis.categoryGap, bandWidth); |
|
var barGapPercent = parsePercent(columnsOnAxis.gap, 1); |
|
var remainedWidth = columnsOnAxis.remainedWidth; |
|
var autoWidthCount = columnsOnAxis.autoWidthCount; |
|
var autoWidth = (remainedWidth - categoryGap) / (autoWidthCount + (autoWidthCount - 1) * barGapPercent); |
|
autoWidth = Math.max(autoWidth, 0); // Find if any auto calculated bar exceeded maxBarWidth |
|
|
|
zrUtil.each(stacks, function (column, stack) { |
|
var maxWidth = column.maxWidth; |
|
|
|
if (maxWidth && maxWidth < autoWidth) { |
|
maxWidth = Math.min(maxWidth, remainedWidth); |
|
|
|
if (column.width) { |
|
maxWidth = Math.min(maxWidth, column.width); |
|
} |
|
|
|
remainedWidth -= maxWidth; |
|
column.width = maxWidth; |
|
autoWidthCount--; |
|
} |
|
}); // Recalculate width again |
|
|
|
autoWidth = (remainedWidth - categoryGap) / (autoWidthCount + (autoWidthCount - 1) * barGapPercent); |
|
autoWidth = Math.max(autoWidth, 0); |
|
var widthSum = 0; |
|
var lastColumn; |
|
zrUtil.each(stacks, function (column, idx) { |
|
if (!column.width) { |
|
column.width = autoWidth; |
|
} |
|
|
|
lastColumn = column; |
|
widthSum += column.width * (1 + barGapPercent); |
|
}); |
|
|
|
if (lastColumn) { |
|
widthSum -= lastColumn.width * barGapPercent; |
|
} |
|
|
|
var offset = -widthSum / 2; |
|
zrUtil.each(stacks, function (column, stackId) { |
|
result[coordSysName][stackId] = result[coordSysName][stackId] || { |
|
offset: offset, |
|
width: column.width |
|
}; |
|
offset += column.width * (1 + barGapPercent); |
|
}); |
|
}); |
|
return result; |
|
} |
|
|
|
export default barLayoutPolar; |