diff --git a/src/processor/dataStack.ts b/src/processor/dataStack.ts index 42f7779ba6..824e630594 100644 --- a/src/processor/dataStack.ts +++ b/src/processor/dataStack.ts @@ -39,13 +39,13 @@ type StackInfo = Pick< // (1) [Caution]: the logic is correct based on the premises: // data processing stage is blocked in stream. // See -// (2) Only register once when import repeatly. -// Should be executed after series filtered and before stack calculation. +// (2) Only register once when import repeatedly. +// Should be executed after series is filtered and before stack calculation. export default function dataStack(ecModel: GlobalModel) { const stackInfoMap = createHashMap(); ecModel.eachSeries(function (seriesModel: SeriesModel) { const stack = seriesModel.get('stack'); - // Compatibal: when `stack` is set as '', do not stack. + // Compatible: when `stack` is set as '', do not stack. if (stack) { const stackInfoList = stackInfoMap.get(stack) || stackInfoMap.set(stack, []); const data = seriesModel.getData(); @@ -87,6 +87,7 @@ function calculateStack(stackInfoList: StackInfo[]) { const dims: [string, string] = [targetStackInfo.stackResultDimension, targetStackInfo.stackedOverDimension]; const targetData = targetStackInfo.data; const isStackedByIndex = targetStackInfo.isStackedByIndex; + const stackStrategy = targetStackInfo.seriesModel.get('stackStrategy') || 'samesign'; // Should not write on raw data, because stack series model list changes // depending on legend selection. @@ -126,12 +127,16 @@ function calculateStack(stackInfoList: StackInfo[]) { ) as number; // Considering positive stack, negative stack and empty data - if ((sum >= 0 && val > 0) // Positive stack - || (sum <= 0 && val < 0) // Negative stack + if ( + stackStrategy === 'all' // single stack group + || (stackStrategy === 'positive' && val > 0) + || (stackStrategy === 'negative' && val < 0) + || (stackStrategy === 'samesign' && sum >= 0 && val > 0) // All positive stack + || (stackStrategy === 'samesign' && sum <= 0 && val < 0) // All negative stack ) { - // The sum should be as less as possible to be effected - // by floating arithmetic problem. A wrong result probably - // filtered incorrectly by axis min/max. + // The sum has to be very small to be affected by the + // floating arithmetic problem. An incorrect result will probably + // cause axis min/max to be filtered incorrectly. sum = addSafe(sum, val); stackedOver = val; break; diff --git a/src/util/types.ts b/src/util/types.ts index c503f48eec..e8d3f1d182 100644 --- a/src/util/types.ts +++ b/src/util/types.ts @@ -1661,6 +1661,7 @@ export interface SeriesLargeOptionMixin { } export interface SeriesStackOptionMixin { stack?: string + stackStrategy?: 'samesign' | 'all' | 'positive' | 'negative'; } type SamplingFunc = (frame: ArrayLike) => number; diff --git a/test/area-stack.html b/test/area-stack.html index 4cc1248738..c60eaa1b64 100644 --- a/test/area-stack.html +++ b/test/area-stack.html @@ -40,13 +40,10 @@
- - - - - - - +
+
+
+
+ + + + + + + - \ No newline at end of file +