/* * 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 _util = require("zrender/lib/core/util"); var createHashMap = _util.createHashMap; var each = _util.each; /* * 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. */ // (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. function _default(ecModel) { var stackInfoMap = createHashMap(); ecModel.eachSeries(function (seriesModel) { var stack = seriesModel.get('stack'); // Compatibal: when `stack` is set as '', do not stack. if (stack) { var stackInfoList = stackInfoMap.get(stack) || stackInfoMap.set(stack, []); var data = seriesModel.getData(); var stackInfo = { // Used for calculate axis extent automatically. stackResultDimension: data.getCalculationInfo('stackResultDimension'), stackedOverDimension: data.getCalculationInfo('stackedOverDimension'), stackedDimension: data.getCalculationInfo('stackedDimension'), stackedByDimension: data.getCalculationInfo('stackedByDimension'), isStackedByIndex: data.getCalculationInfo('isStackedByIndex'), data: data, seriesModel: seriesModel }; // If stacked on axis that do not support data stack. if (!stackInfo.stackedDimension || !(stackInfo.isStackedByIndex || stackInfo.stackedByDimension)) { return; } stackInfoList.length && data.setCalculationInfo('stackedOnSeries', stackInfoList[stackInfoList.length - 1].seriesModel); stackInfoList.push(stackInfo); } }); stackInfoMap.each(calculateStack); } function calculateStack(stackInfoList) { each(stackInfoList, function (targetStackInfo, idxInStack) { var resultVal = []; var resultNaN = [NaN, NaN]; var dims = [targetStackInfo.stackResultDimension, targetStackInfo.stackedOverDimension]; var targetData = targetStackInfo.data; var isStackedByIndex = targetStackInfo.isStackedByIndex; // Should not write on raw data, because stack series model list changes // depending on legend selection. var newData = targetData.map(dims, function (v0, v1, dataIndex) { var sum = targetData.get(targetStackInfo.stackedDimension, dataIndex); // Consider `connectNulls` of line area, if value is NaN, stackedOver // should also be NaN, to draw a appropriate belt area. if (isNaN(sum)) { return resultNaN; } var byValue; var stackedDataRawIndex; if (isStackedByIndex) { stackedDataRawIndex = targetData.getRawIndex(dataIndex); } else { byValue = targetData.get(targetStackInfo.stackedByDimension, dataIndex); } // If stackOver is NaN, chart view will render point on value start. var stackedOver = NaN; for (var j = idxInStack - 1; j >= 0; j--) { var stackInfo = stackInfoList[j]; // Has been optimized by inverted indices on `stackedByDimension`. if (!isStackedByIndex) { stackedDataRawIndex = stackInfo.data.rawIndexOf(stackInfo.stackedByDimension, byValue); } if (stackedDataRawIndex >= 0) { var val = stackInfo.data.getByRawIndex(stackInfo.stackResultDimension, stackedDataRawIndex); // Considering positive stack, negative stack and empty data if (sum >= 0 && val > 0 || // Positive stack sum <= 0 && val < 0 // Negative stack ) { sum += val; stackedOver = val; break; } } } resultVal[0] = sum; resultVal[1] = stackedOver; return resultVal; }); targetData.hostModel.setData(newData); // Update for consequent calculation targetStackInfo.data = newData; }); } module.exports = _default;