|  | /* | 
|  | * 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/src/core/util'; | 
|  | import createSeriesDataSimply from '../helper/createSeriesDataSimply'; | 
|  | import {defaultEmphasis} from '../../util/model'; | 
|  | import {makeSeriesEncodeForNameBased} from '../../data/helper/sourceHelper'; | 
|  | import LegendVisualProvider from '../../visual/LegendVisualProvider'; | 
|  | import SeriesModel from '../../model/Series'; | 
|  | import { | 
|  | SeriesOption, | 
|  | BoxLayoutOptionMixin, | 
|  | HorizontalAlign, | 
|  | LabelOption, | 
|  | LabelLineOption, | 
|  | ItemStyleOption, | 
|  | OptionDataValueNumeric, | 
|  | StatesOptionMixin, | 
|  | OptionDataItemObject, | 
|  | LayoutOrient, | 
|  | VerticalAlign, | 
|  | SeriesLabelOption, | 
|  | SeriesEncodeOptionMixin, | 
|  | DefaultStatesMixinEmphasis, | 
|  | CallbackDataParams | 
|  | } from '../../util/types'; | 
|  | import GlobalModel from '../../model/Global'; | 
|  | import SeriesData from '../../data/SeriesData'; | 
|  |  | 
|  | type FunnelLabelOption = Omit<SeriesLabelOption, 'position'> & { | 
|  | position?: LabelOption['position'] | 
|  | | 'outer' | 'inner' | 'center' | 'rightTop' | 'rightBottom' | 'leftTop' | 'leftBottom' | 
|  | }; | 
|  |  | 
|  | interface FunnelStatesMixin { | 
|  | emphasis?: DefaultStatesMixinEmphasis | 
|  | } | 
|  |  | 
|  | export interface FunnelCallbackDataParams extends CallbackDataParams { | 
|  | percent: number | 
|  | } | 
|  | export interface FunnelStateOption<TCbParams = never> { | 
|  | itemStyle?: ItemStyleOption<TCbParams> | 
|  | label?: FunnelLabelOption | 
|  | labelLine?: LabelLineOption | 
|  | } | 
|  |  | 
|  | export interface FunnelDataItemOption | 
|  | extends FunnelStateOption, StatesOptionMixin<FunnelStateOption, FunnelStatesMixin>, | 
|  | OptionDataItemObject<OptionDataValueNumeric> { | 
|  |  | 
|  | itemStyle?: ItemStyleOption & { | 
|  | width?: number | string | 
|  | height?: number | string | 
|  | } | 
|  | } | 
|  |  | 
|  | export interface FunnelSeriesOption | 
|  | extends SeriesOption<FunnelStateOption<FunnelCallbackDataParams>, FunnelStatesMixin>, | 
|  | FunnelStateOption<FunnelCallbackDataParams>, | 
|  | BoxLayoutOptionMixin, SeriesEncodeOptionMixin { | 
|  | type?: 'funnel' | 
|  |  | 
|  | min?: number | 
|  | max?: number | 
|  |  | 
|  | /** | 
|  | * Absolute number or percent string | 
|  | */ | 
|  | minSize?: number | string | 
|  | maxSize?: number | string | 
|  |  | 
|  | sort?: 'ascending' | 'descending' | 'none' | 
|  |  | 
|  | orient?: LayoutOrient | 
|  |  | 
|  | gap?: number | 
|  |  | 
|  | funnelAlign?: HorizontalAlign | VerticalAlign | 
|  |  | 
|  | data?: (OptionDataValueNumeric | OptionDataValueNumeric[] | FunnelDataItemOption)[] | 
|  | } | 
|  |  | 
|  | class FunnelSeriesModel extends SeriesModel<FunnelSeriesOption> { | 
|  | static type = 'series.funnel' as const; | 
|  | type = FunnelSeriesModel.type; | 
|  |  | 
|  | init(option: FunnelSeriesOption) { | 
|  | super.init.apply(this, arguments as any); | 
|  |  | 
|  | // Enable legend selection for each data item | 
|  | // Use a function instead of direct access because data reference may changed | 
|  | this.legendVisualProvider = new LegendVisualProvider( | 
|  | zrUtil.bind(this.getData, this), zrUtil.bind(this.getRawData, this) | 
|  | ); | 
|  | // Extend labelLine emphasis | 
|  | this._defaultLabelLine(option); | 
|  | } | 
|  |  | 
|  | getInitialData(this: FunnelSeriesModel, option: FunnelSeriesOption, ecModel: GlobalModel): SeriesData { | 
|  | return createSeriesDataSimply(this, { | 
|  | coordDimensions: ['value'], | 
|  | encodeDefaulter: zrUtil.curry(makeSeriesEncodeForNameBased, this) | 
|  | }); | 
|  | } | 
|  |  | 
|  | _defaultLabelLine(option: FunnelSeriesOption) { | 
|  | // Extend labelLine emphasis | 
|  | defaultEmphasis(option, 'labelLine', ['show']); | 
|  |  | 
|  | const labelLineNormalOpt = option.labelLine; | 
|  | const labelLineEmphasisOpt = option.emphasis.labelLine; | 
|  | // Not show label line if `label.normal.show = false` | 
|  | labelLineNormalOpt.show = labelLineNormalOpt.show | 
|  | && option.label.show; | 
|  | labelLineEmphasisOpt.show = labelLineEmphasisOpt.show | 
|  | && option.emphasis.label.show; | 
|  | } | 
|  |  | 
|  | // Overwrite | 
|  | getDataParams(dataIndex: number): FunnelCallbackDataParams { | 
|  | const data = this.getData(); | 
|  | const params = super.getDataParams(dataIndex) as FunnelCallbackDataParams; | 
|  | const valueDim = data.mapDimension('value'); | 
|  | const sum = data.getSum(valueDim); | 
|  | // Percent is 0 if sum is 0 | 
|  | params.percent = !sum ? 0 : +(data.get(valueDim, dataIndex) as number / sum * 100).toFixed(2); | 
|  |  | 
|  | params.$vars.push('percent'); | 
|  | return params; | 
|  | } | 
|  |  | 
|  | static defaultOption: FunnelSeriesOption = { | 
|  | // zlevel: 0,                  // 一级层叠 | 
|  | z: 2,                       // 二级层叠 | 
|  | legendHoverLink: true, | 
|  | colorBy: 'data', | 
|  | left: 80, | 
|  | top: 60, | 
|  | right: 80, | 
|  | bottom: 60, | 
|  | // width: {totalWidth} - left - right, | 
|  | // height: {totalHeight} - top - bottom, | 
|  |  | 
|  | // 默认取数据最小最大值 | 
|  | // min: 0, | 
|  | // max: 100, | 
|  | minSize: '0%', | 
|  | maxSize: '100%', | 
|  | sort: 'descending', // 'ascending', 'descending' | 
|  | orient: 'vertical', | 
|  | gap: 0, | 
|  | funnelAlign: 'center', | 
|  | label: { | 
|  | show: true, | 
|  | position: 'outer' | 
|  | // formatter: 标签文本格式器,同Tooltip.formatter,不支持异步回调 | 
|  | }, | 
|  | labelLine: { | 
|  | show: true, | 
|  | length: 20, | 
|  | lineStyle: { | 
|  | // color: 各异, | 
|  | width: 1 | 
|  | } | 
|  | }, | 
|  | itemStyle: { | 
|  | // color: 各异, | 
|  | borderColor: '#fff', | 
|  | borderWidth: 1 | 
|  | }, | 
|  | emphasis: { | 
|  | label: { | 
|  | show: true | 
|  | } | 
|  | }, | 
|  | select: { | 
|  | itemStyle: { | 
|  | borderColor: '#212121' | 
|  | } | 
|  | } | 
|  | }; | 
|  |  | 
|  | } | 
|  |  | 
|  | export default FunnelSeriesModel; |