|   | 
| /* | 
| * 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 layout from '../../util/layout.js'; | 
| import { parsePercent, linearMap } from '../../util/number.js'; | 
| import { isFunction } from 'zrender/lib/core/util.js'; | 
| 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 (isFunction(sort)) { | 
|     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) { | 
|   var seriesModel = data.hostModel; | 
|   var orient = seriesModel.get('orient'); | 
|   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' || labelPosition === 'insideLeft' || labelPosition === 'insideRight'; | 
|     var textAlign; | 
|     var textX; | 
|     var textY; | 
|     var linePoints; | 
|     if (isLabelInside) { | 
|       if (labelPosition === 'insideLeft') { | 
|         textX = (points[0][0] + points[3][0]) / 2 + 5; | 
|         textY = (points[0][1] + points[3][1]) / 2; | 
|         textAlign = 'left'; | 
|       } else if (labelPosition === 'insideRight') { | 
|         textX = (points[1][0] + points[2][0]) / 2 - 5; | 
|         textY = (points[1][1] + points[2][1]) / 2; | 
|         textAlign = 'right'; | 
|       } else { | 
|         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 = void 0; | 
|       var y1 = void 0; | 
|       var x2 = void 0; | 
|       var y2 = void 0; | 
|       var labelLineLen = labelLineModel.get('length'); | 
|       if (process.env.NODE_ENV !== 'production') { | 
|         if (orient === 'vertical' && ['top', 'bottom'].indexOf(labelPosition) > -1) { | 
|           labelPosition = 'left'; | 
|           console.warn('Position error: Funnel chart on vertical orient dose not support top and bottom.'); | 
|         } | 
|         if (orient === 'horizontal' && ['left', 'right'].indexOf(labelPosition) > -1) { | 
|           labelPosition = 'bottom'; | 
|           console.warn('Position error: Funnel chart on horizontal orient dose not support left and right.'); | 
|         } | 
|       } | 
|       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 if (labelPosition === 'right') { | 
|         // 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'; | 
|       } else if (labelPosition === 'top') { | 
|         // Top side | 
|         x1 = (points[3][0] + points[0][0]) / 2; | 
|         y1 = (points[3][1] + points[0][1]) / 2; | 
|         y2 = y1 - labelLineLen; | 
|         textY = y2 - 5; | 
|         textAlign = 'center'; | 
|       } else if (labelPosition === 'bottom') { | 
|         // Bottom side | 
|         x1 = (points[1][0] + points[2][0]) / 2; | 
|         y1 = (points[1][1] + points[2][1]) / 2; | 
|         y2 = y1 + labelLineLen; | 
|         textY = y2 + 5; | 
|         textAlign = 'center'; | 
|       } else if (labelPosition === 'rightTop') { | 
|         // RightTop side | 
|         x1 = orient === 'horizontal' ? points[3][0] : points[1][0]; | 
|         y1 = orient === 'horizontal' ? points[3][1] : points[1][1]; | 
|         if (orient === 'horizontal') { | 
|           y2 = y1 - labelLineLen; | 
|           textY = y2 - 5; | 
|           textAlign = 'center'; | 
|         } else { | 
|           x2 = x1 + labelLineLen; | 
|           textX = x2 + 5; | 
|           textAlign = 'top'; | 
|         } | 
|       } else if (labelPosition === 'rightBottom') { | 
|         // RightBottom side | 
|         x1 = points[2][0]; | 
|         y1 = points[2][1]; | 
|         if (orient === 'horizontal') { | 
|           y2 = y1 + labelLineLen; | 
|           textY = y2 + 5; | 
|           textAlign = 'center'; | 
|         } else { | 
|           x2 = x1 + labelLineLen; | 
|           textX = x2 + 5; | 
|           textAlign = 'bottom'; | 
|         } | 
|       } else if (labelPosition === 'leftTop') { | 
|         // LeftTop side | 
|         x1 = points[0][0]; | 
|         y1 = orient === 'horizontal' ? points[0][1] : points[1][1]; | 
|         if (orient === 'horizontal') { | 
|           y2 = y1 - labelLineLen; | 
|           textY = y2 - 5; | 
|           textAlign = 'center'; | 
|         } else { | 
|           x2 = x1 - labelLineLen; | 
|           textX = x2 - 5; | 
|           textAlign = 'right'; | 
|         } | 
|       } else if (labelPosition === 'leftBottom') { | 
|         // LeftBottom side | 
|         x1 = orient === 'horizontal' ? points[1][0] : points[3][0]; | 
|         y1 = orient === 'horizontal' ? points[1][1] : points[2][1]; | 
|         if (orient === 'horizontal') { | 
|           y2 = y1 + labelLineLen; | 
|           textY = y2 + 5; | 
|           textAlign = 'center'; | 
|         } else { | 
|           x2 = x1 - labelLineLen; | 
|           textX = x2 - 5; | 
|           textAlign = 'right'; | 
|         } | 
|       } else { | 
|         // Right side or Bottom side | 
|         x1 = (points[1][0] + points[2][0]) / 2; | 
|         y1 = (points[1][1] + points[2][1]) / 2; | 
|         if (orient === 'horizontal') { | 
|           y2 = y1 + labelLineLen; | 
|           textY = y2 + 5; | 
|           textAlign = 'center'; | 
|         } else { | 
|           x2 = x1 + labelLineLen; | 
|           textX = x2 + 5; | 
|           textAlign = 'left'; | 
|         } | 
|       } | 
|       if (orient === 'horizontal') { | 
|         x2 = x1; | 
|         textX = x2; | 
|       } else { | 
|         y2 = y1; | 
|         textY = y2; | 
|       } | 
|       linePoints = [[x1, y1], [x2, y2]]; | 
|     } | 
|     layout.label = { | 
|       linePoints: linePoints, | 
|       x: textX, | 
|       y: textY, | 
|       verticalAlign: 'middle', | 
|       textAlign: textAlign, | 
|       inside: isLabelInside | 
|     }; | 
|   }); | 
| } | 
| export default function funnelLayout(ecModel, api) { | 
|   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 orient = seriesModel.get('orient'); | 
|     var viewWidth = viewRect.width; | 
|     var viewHeight = viewRect.height; | 
|     var indices = getSortedIndices(data, sort); | 
|     var x = viewRect.x; | 
|     var y = viewRect.y; | 
|     var sizeExtent = orient === 'horizontal' ? [parsePercent(seriesModel.get('minSize'), viewHeight), parsePercent(seriesModel.get('maxSize'), viewHeight)] : [parsePercent(seriesModel.get('minSize'), viewWidth), parsePercent(seriesModel.get('maxSize'), viewWidth)]; | 
|     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 viewSize = orient === 'horizontal' ? viewWidth : viewHeight; | 
|     var itemSize = (viewSize - gap * (data.count() - 1)) / data.count(); | 
|     var getLinePoints = function (idx, offset) { | 
|       // End point index is data.count() and we assign it 0 | 
|       if (orient === 'horizontal') { | 
|         var val_1 = data.get(valueDim, idx) || 0; | 
|         var itemHeight = linearMap(val_1, [min, max], sizeExtent, true); | 
|         var y0 = void 0; | 
|         switch (funnelAlign) { | 
|           case 'top': | 
|             y0 = y; | 
|             break; | 
|           case 'center': | 
|             y0 = y + (viewHeight - itemHeight) / 2; | 
|             break; | 
|           case 'bottom': | 
|             y0 = y + (viewHeight - itemHeight); | 
|             break; | 
|         } | 
|         return [[offset, y0], [offset, y0 + itemHeight]]; | 
|       } | 
|       var val = data.get(valueDim, idx) || 0; | 
|       var itemWidth = linearMap(val, [min, max], sizeExtent, true); | 
|       var x0; | 
|       switch (funnelAlign) { | 
|         case 'left': | 
|           x0 = x; | 
|           break; | 
|         case 'center': | 
|           x0 = x + (viewWidth - itemWidth) / 2; | 
|           break; | 
|         case 'right': | 
|           x0 = x + viewWidth - itemWidth; | 
|           break; | 
|       } | 
|       return [[x0, offset], [x0 + itemWidth, offset]]; | 
|     }; | 
|     if (sort === 'ascending') { | 
|       // From bottom to top | 
|       itemSize = -itemSize; | 
|       gap = -gap; | 
|       if (orient === 'horizontal') { | 
|         x += viewWidth; | 
|       } else { | 
|         y += viewHeight; | 
|       } | 
|       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); | 
|       if (orient === 'horizontal') { | 
|         var width = itemModel.get(['itemStyle', 'width']); | 
|         if (width == null) { | 
|           width = itemSize; | 
|         } else { | 
|           width = parsePercent(width, viewWidth); | 
|           if (sort === 'ascending') { | 
|             width = -width; | 
|           } | 
|         } | 
|         var start = getLinePoints(idx, x); | 
|         var end = getLinePoints(nextIdx, x + width); | 
|         x += width + gap; | 
|         data.setItemLayout(idx, { | 
|           points: start.concat(end.slice().reverse()) | 
|         }); | 
|       } else { | 
|         var height = itemModel.get(['itemStyle', 'height']); | 
|         if (height == null) { | 
|           height = itemSize; | 
|         } else { | 
|           height = parsePercent(height, viewHeight); | 
|           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); | 
|   }); | 
| } |