Spaces:
Running
Running
| /* | |
| * 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 * as zrColor from 'zrender/src/tool/color'; | |
| import {linearMap} from '../util/number'; | |
| import { AllPropTypes, Dictionary } from 'zrender/src/core/types'; | |
| import { | |
| ColorString, | |
| BuiltinVisualProperty, | |
| VisualOptionPiecewise, | |
| VisualOptionUnit, | |
| ParsedValue | |
| } from '../util/types'; | |
| import { warn } from '../util/log'; | |
| const each = zrUtil.each; | |
| const isObject = zrUtil.isObject; | |
| const CATEGORY_DEFAULT_VISUAL_INDEX = -1; | |
| // Type of raw value | |
| type RawValue = ParsedValue; | |
| // Type of mapping visual value | |
| type VisualValue = AllPropTypes<VisualOptionUnit>; | |
| // Type of value after normalized. 0 - 1 | |
| type NormalizedValue = number; | |
| type MappingMethod = 'linear' | 'piecewise' | 'category' | 'fixed'; | |
| // May include liftZ. which is not provided to developers. | |
| interface Normalizer { | |
| (this: VisualMapping, value?: RawValue): NormalizedValue | |
| } | |
| interface ColorMapper { | |
| (this: VisualMapping, value: RawValue | NormalizedValue, isNormalized?: boolean, out?: number[]) | |
| : ColorString | number[] | |
| } | |
| interface DoMap { | |
| (this: VisualMapping, normalzied?: NormalizedValue, value?: RawValue): VisualValue | |
| } | |
| interface VisualValueGetter { | |
| (key: string): VisualValue | |
| } | |
| interface VisualValueSetter { | |
| (key: string, value: VisualValue): void | |
| } | |
| interface VisualHandler { | |
| applyVisual( | |
| this: VisualMapping, | |
| value: RawValue, | |
| getter: VisualValueGetter, | |
| setter: VisualValueSetter | |
| ): void | |
| _normalizedToVisual: { | |
| linear(this: VisualMapping, normalized: NormalizedValue): VisualValue | |
| category(this: VisualMapping, normalized: NormalizedValue): VisualValue | |
| piecewise(this: VisualMapping, normalzied: NormalizedValue, value: RawValue): VisualValue | |
| fixed(this: VisualMapping): VisualValue | |
| } | |
| /** | |
| * Get color mapping for the outside usage. | |
| * Currently only used in `color` visual. | |
| * | |
| * The last parameter out is cached color array. | |
| */ | |
| getColorMapper?: (this: VisualMapping) => ColorMapper | |
| } | |
| interface VisualMappingPiece { | |
| index?: number | |
| value?: number | string | |
| interval?: [number, number] | |
| close?: [0 | 1, 0 | 1] | |
| text?: string | |
| visual?: VisualOptionPiecewise | |
| } | |
| export interface VisualMappingOption { | |
| type?: BuiltinVisualProperty | |
| mappingMethod?: MappingMethod | |
| /** | |
| * required when mappingMethod is 'linear' | |
| */ | |
| dataExtent?: [number, number] | |
| /** | |
| * required when mappingMethod is 'piecewise'. | |
| * Visual for only each piece can be specified | |
| * [ | |
| * {value: someValue}, | |
| * {interval: [min1, max1], visual: {...}}, | |
| * {interval: [min2, max2]} | |
| * ],. | |
| */ | |
| pieceList?: VisualMappingPiece[] | |
| /** | |
| * required when mappingMethod is 'category'. If no option.categories, categories is set as [0, 1, 2, ...]. | |
| */ | |
| categories?: (string | number)[] | |
| /** | |
| * Whether loop mapping when mappingMethod is 'category'. | |
| * @default false | |
| */ | |
| loop?: boolean | |
| /** | |
| * Visual data | |
| * when mappingMethod is 'category', visual data can be array or object | |
| * (like: {cate1: '#222', none: '#fff'}) | |
| * or primary types (which represents default category visual), otherwise visual | |
| * can be array or primary (which will be normalized to array). | |
| */ | |
| visual?: VisualValue[] | Dictionary<VisualValue> | VisualValue | |
| } | |
| interface VisualMappingInnerPiece extends VisualMappingPiece { | |
| originIndex: number | |
| } | |
| interface VisualMappingInnerOption extends VisualMappingOption { | |
| hasSpecialVisual: boolean | |
| pieceList: VisualMappingInnerPiece[] | |
| /** | |
| * Map to get category index | |
| */ | |
| categoryMap: Dictionary<number> | |
| /** | |
| * Cached parsed rgba array from string to avoid parse every time. | |
| */ | |
| parsedVisual: number[][] | |
| // Have converted primary value to array. | |
| visual?: VisualValue[] | Dictionary<VisualValue> | |
| } | |
| class VisualMapping { | |
| option: VisualMappingInnerOption; | |
| type: BuiltinVisualProperty; | |
| mappingMethod: MappingMethod; | |
| applyVisual: VisualHandler['applyVisual']; | |
| getColorMapper: VisualHandler['getColorMapper']; | |
| _normalizeData: Normalizer; | |
| _normalizedToVisual: DoMap; | |
| constructor(option: VisualMappingOption) { | |
| const mappingMethod = option.mappingMethod; | |
| const visualType = option.type; | |
| const thisOption: VisualMappingInnerOption = this.option = zrUtil.clone(option) as VisualMappingInnerOption; | |
| this.type = visualType; | |
| this.mappingMethod = mappingMethod; | |
| this._normalizeData = normalizers[mappingMethod]; | |
| const visualHandler = VisualMapping.visualHandlers[visualType]; | |
| this.applyVisual = visualHandler.applyVisual; | |
| this.getColorMapper = visualHandler.getColorMapper; | |
| this._normalizedToVisual = visualHandler._normalizedToVisual[mappingMethod]; | |
| if (mappingMethod === 'piecewise') { | |
| normalizeVisualRange(thisOption); | |
| preprocessForPiecewise(thisOption); | |
| } | |
| else if (mappingMethod === 'category') { | |
| thisOption.categories | |
| ? preprocessForSpecifiedCategory(thisOption) | |
| // categories is ordinal when thisOption.categories not specified, | |
| // which need no more preprocess except normalize visual. | |
| : normalizeVisualRange(thisOption, true); | |
| } | |
| else { // mappingMethod === 'linear' or 'fixed' | |
| zrUtil.assert(mappingMethod !== 'linear' || thisOption.dataExtent); | |
| normalizeVisualRange(thisOption); | |
| } | |
| } | |
| mapValueToVisual(value: RawValue): VisualValue { | |
| const normalized = this._normalizeData(value); | |
| return this._normalizedToVisual(normalized, value); | |
| } | |
| getNormalizer() { | |
| return zrUtil.bind(this._normalizeData, this); | |
| } | |
| static visualHandlers: {[key in BuiltinVisualProperty]: VisualHandler} = { | |
| color: { | |
| applyVisual: makeApplyVisual('color'), | |
| getColorMapper: function () { | |
| const thisOption = this.option; | |
| return zrUtil.bind( | |
| thisOption.mappingMethod === 'category' | |
| ? function ( | |
| this: VisualMapping, | |
| value: NormalizedValue | RawValue, | |
| isNormalized?: boolean | |
| ): ColorString { | |
| !isNormalized && (value = this._normalizeData(value)); | |
| return doMapCategory.call(this, value) as ColorString; | |
| } | |
| : function ( | |
| this: VisualMapping, | |
| value: NormalizedValue | RawValue, | |
| isNormalized?: boolean, | |
| out?: number[] | |
| ): number[] | string { | |
| // If output rgb array | |
| // which will be much faster and useful in pixel manipulation | |
| const returnRGBArray = !!out; | |
| !isNormalized && (value = this._normalizeData(value)); | |
| out = zrColor.fastLerp(value as NormalizedValue, thisOption.parsedVisual, out); | |
| return returnRGBArray ? out : zrColor.stringify(out, 'rgba'); | |
| }, | |
| this | |
| ); | |
| }, | |
| _normalizedToVisual: { | |
| linear: function (normalized) { | |
| return zrColor.stringify( | |
| zrColor.fastLerp(normalized, this.option.parsedVisual), | |
| 'rgba' | |
| ); | |
| }, | |
| category: doMapCategory, | |
| piecewise: function (normalized, value) { | |
| let result = getSpecifiedVisual.call(this, value); | |
| if (result == null) { | |
| result = zrColor.stringify( | |
| zrColor.fastLerp(normalized, this.option.parsedVisual), | |
| 'rgba' | |
| ); | |
| } | |
| return result; | |
| }, | |
| fixed: doMapFixed | |
| } | |
| }, | |
| colorHue: makePartialColorVisualHandler(function (color: ColorString, value: number) { | |
| return zrColor.modifyHSL(color, value); | |
| }), | |
| colorSaturation: makePartialColorVisualHandler(function (color: ColorString, value: number) { | |
| return zrColor.modifyHSL(color, null, value); | |
| }), | |
| colorLightness: makePartialColorVisualHandler(function (color: ColorString, value: number) { | |
| return zrColor.modifyHSL(color, null, null, value); | |
| }), | |
| colorAlpha: makePartialColorVisualHandler(function (color: ColorString, value: number) { | |
| return zrColor.modifyAlpha(color, value); | |
| }), | |
| decal: { | |
| applyVisual: makeApplyVisual('decal'), | |
| _normalizedToVisual: { | |
| linear: null, | |
| category: doMapCategory, | |
| piecewise: null, | |
| fixed: null | |
| } | |
| }, | |
| opacity: { | |
| applyVisual: makeApplyVisual('opacity'), | |
| _normalizedToVisual: createNormalizedToNumericVisual([0, 1]) | |
| }, | |
| liftZ: { | |
| applyVisual: makeApplyVisual('liftZ'), | |
| _normalizedToVisual: { | |
| linear: doMapFixed, | |
| category: doMapFixed, | |
| piecewise: doMapFixed, | |
| fixed: doMapFixed | |
| } | |
| }, | |
| symbol: { | |
| applyVisual: function (value, getter, setter) { | |
| const symbolCfg = this.mapValueToVisual(value); | |
| setter('symbol', symbolCfg as string); | |
| }, | |
| _normalizedToVisual: { | |
| linear: doMapToArray, | |
| category: doMapCategory, | |
| piecewise: function (normalized, value) { | |
| let result = getSpecifiedVisual.call(this, value); | |
| if (result == null) { | |
| result = doMapToArray.call(this, normalized); | |
| } | |
| return result; | |
| }, | |
| fixed: doMapFixed | |
| } | |
| }, | |
| symbolSize: { | |
| applyVisual: makeApplyVisual('symbolSize'), | |
| _normalizedToVisual: createNormalizedToNumericVisual([0, 1]) | |
| } | |
| }; | |
| /** | |
| * List available visual types. | |
| * | |
| * @public | |
| * @return {Array.<string>} | |
| */ | |
| static listVisualTypes() { | |
| return zrUtil.keys(VisualMapping.visualHandlers); | |
| } | |
| // /** | |
| // * @public | |
| // */ | |
| // static addVisualHandler(name, handler) { | |
| // visualHandlers[name] = handler; | |
| // } | |
| /** | |
| * @public | |
| */ | |
| static isValidType(visualType: string): boolean { | |
| return VisualMapping.visualHandlers.hasOwnProperty(visualType); | |
| } | |
| /** | |
| * Convenient method. | |
| * Visual can be Object or Array or primary type. | |
| */ | |
| static eachVisual<Ctx, T>( | |
| visual: T | T[] | Dictionary<T>, | |
| callback: (visual: T, key?: string | number) => void, | |
| context?: Ctx | |
| ) { | |
| if (zrUtil.isObject(visual)) { | |
| zrUtil.each(visual as Dictionary<T>, callback, context); | |
| } | |
| else { | |
| callback.call(context, visual); | |
| } | |
| } | |
| static mapVisual<Ctx, T>(visual: T, callback: (visual: T, key?: string | number) => T, context?: Ctx): T; | |
| static mapVisual<Ctx, T>(visual: T[], callback: (visual: T, key?: string | number) => T[], context?: Ctx): T[]; | |
| static mapVisual<Ctx, T>( | |
| visual: Dictionary<T>, | |
| callback: (visual: T, key?: string | number) => Dictionary<T>, | |
| context?: Ctx | |
| ): Dictionary<T>; | |
| static mapVisual<Ctx, T>( | |
| visual: T | T[] | Dictionary<T>, | |
| callback: (visual: T, key?: string | number) => T | T[] | Dictionary<T>, | |
| context?: Ctx | |
| ) { | |
| let isPrimary: boolean; | |
| let newVisual: T | T[] | Dictionary<T> = zrUtil.isArray(visual) | |
| ? [] | |
| : zrUtil.isObject(visual) | |
| ? {} | |
| : (isPrimary = true, null); | |
| VisualMapping.eachVisual(visual, function (v, key) { | |
| const newVal = callback.call(context, v, key); | |
| isPrimary ? (newVisual = newVal) : ((newVisual as Dictionary<T>)[key as string] = newVal as T); | |
| }); | |
| return newVisual; | |
| } | |
| /** | |
| * Retrieve visual properties from given object. | |
| */ | |
| static retrieveVisuals(obj: Dictionary<any>): VisualOptionPiecewise { | |
| const ret: VisualOptionPiecewise = {}; | |
| let hasVisual: boolean; | |
| obj && each(VisualMapping.visualHandlers, function (h, visualType: BuiltinVisualProperty) { | |
| if (obj.hasOwnProperty(visualType)) { | |
| (ret as any)[visualType] = obj[visualType]; | |
| hasVisual = true; | |
| } | |
| }); | |
| return hasVisual ? ret : null; | |
| } | |
| /** | |
| * Give order to visual types, considering colorSaturation, colorAlpha depends on color. | |
| * | |
| * @public | |
| * @param {(Object|Array)} visualTypes If Object, like: {color: ..., colorSaturation: ...} | |
| * IF Array, like: ['color', 'symbol', 'colorSaturation'] | |
| * @return {Array.<string>} Sorted visual types. | |
| */ | |
| static prepareVisualTypes( | |
| visualTypes: {[key in BuiltinVisualProperty]?: any} | BuiltinVisualProperty[] | |
| ) { | |
| if (zrUtil.isArray(visualTypes)) { | |
| visualTypes = visualTypes.slice(); | |
| } | |
| else if (isObject(visualTypes)) { | |
| const types: BuiltinVisualProperty[] = []; | |
| each(visualTypes, function (item: unknown, type: BuiltinVisualProperty) { | |
| types.push(type); | |
| }); | |
| visualTypes = types; | |
| } | |
| else { | |
| return []; | |
| } | |
| visualTypes.sort(function (type1: BuiltinVisualProperty, type2: BuiltinVisualProperty) { | |
| // color should be front of colorSaturation, colorAlpha, ... | |
| // symbol and symbolSize do not matter. | |
| return (type2 === 'color' && type1 !== 'color' && type1.indexOf('color') === 0) | |
| ? 1 : -1; | |
| }); | |
| return visualTypes; | |
| } | |
| /** | |
| * 'color', 'colorSaturation', 'colorAlpha', ... are depends on 'color'. | |
| * Other visuals are only depends on themself. | |
| */ | |
| static dependsOn(visualType1: BuiltinVisualProperty, visualType2: BuiltinVisualProperty) { | |
| return visualType2 === 'color' | |
| ? !!(visualType1 && visualType1.indexOf(visualType2) === 0) | |
| : visualType1 === visualType2; | |
| } | |
| /** | |
| * @param value | |
| * @param pieceList [{value: ..., interval: [min, max]}, ...] | |
| * Always from small to big. | |
| * @param findClosestWhenOutside Default to be false | |
| * @return index | |
| */ | |
| static findPieceIndex(value: number, pieceList: VisualMappingPiece[], findClosestWhenOutside?: boolean): number { | |
| let possibleI: number; | |
| let abs = Infinity; | |
| // value has the higher priority. | |
| for (let i = 0, len = pieceList.length; i < len; i++) { | |
| const pieceValue = pieceList[i].value; | |
| if (pieceValue != null) { | |
| if (pieceValue === value | |
| // FIXME | |
| // It is supposed to compare value according to value type of dimension, | |
| // but currently value type can exactly be string or number. | |
| // Compromise for numeric-like string (like '12'), especially | |
| // in the case that visualMap.categories is ['22', '33']. | |
| || (zrUtil.isString(pieceValue) && pieceValue === value + '') | |
| ) { | |
| return i; | |
| } | |
| findClosestWhenOutside && updatePossible(pieceValue as number, i); | |
| } | |
| } | |
| for (let i = 0, len = pieceList.length; i < len; i++) { | |
| const piece = pieceList[i]; | |
| const interval = piece.interval; | |
| const close = piece.close; | |
| if (interval) { | |
| if (interval[0] === -Infinity) { | |
| if (littleThan(close[1], value, interval[1])) { | |
| return i; | |
| } | |
| } | |
| else if (interval[1] === Infinity) { | |
| if (littleThan(close[0], interval[0], value)) { | |
| return i; | |
| } | |
| } | |
| else if ( | |
| littleThan(close[0], interval[0], value) | |
| && littleThan(close[1], value, interval[1]) | |
| ) { | |
| return i; | |
| } | |
| findClosestWhenOutside && updatePossible(interval[0], i); | |
| findClosestWhenOutside && updatePossible(interval[1], i); | |
| } | |
| } | |
| if (findClosestWhenOutside) { | |
| return value === Infinity | |
| ? pieceList.length - 1 | |
| : value === -Infinity | |
| ? 0 | |
| : possibleI; | |
| } | |
| function updatePossible(val: number, index: number) { | |
| const newAbs = Math.abs(val - value); | |
| if (newAbs < abs) { | |
| abs = newAbs; | |
| possibleI = index; | |
| } | |
| } | |
| } | |
| } | |
| function preprocessForPiecewise(thisOption: VisualMappingInnerOption) { | |
| const pieceList = thisOption.pieceList; | |
| thisOption.hasSpecialVisual = false; | |
| zrUtil.each(pieceList, function (piece, index) { | |
| piece.originIndex = index; | |
| // piece.visual is "result visual value" but not | |
| // a visual range, so it does not need to be normalized. | |
| if (piece.visual != null) { | |
| thisOption.hasSpecialVisual = true; | |
| } | |
| }); | |
| } | |
| function preprocessForSpecifiedCategory(thisOption: VisualMappingInnerOption) { | |
| // Hash categories. | |
| const categories = thisOption.categories; | |
| const categoryMap: VisualMappingInnerOption['categoryMap'] = thisOption.categoryMap = {}; | |
| let visual = thisOption.visual; | |
| each(categories, function (cate, index) { | |
| categoryMap[cate] = index; | |
| }); | |
| // Process visual map input. | |
| if (!zrUtil.isArray(visual)) { | |
| const visualArr: VisualValue[] = []; | |
| if (zrUtil.isObject(visual)) { | |
| each(visual, function (v, cate) { | |
| const index = categoryMap[cate]; | |
| visualArr[index != null ? index : CATEGORY_DEFAULT_VISUAL_INDEX] = v; | |
| }); | |
| } | |
| else { // Is primary type, represents default visual. | |
| visualArr[CATEGORY_DEFAULT_VISUAL_INDEX] = visual; | |
| } | |
| visual = setVisualToOption(thisOption, visualArr); | |
| } | |
| // Remove categories that has no visual, | |
| // then we can mapping them to CATEGORY_DEFAULT_VISUAL_INDEX. | |
| for (let i = categories.length - 1; i >= 0; i--) { | |
| if (visual[i] == null) { | |
| delete categoryMap[categories[i]]; | |
| categories.pop(); | |
| } | |
| } | |
| } | |
| function normalizeVisualRange(thisOption: VisualMappingInnerOption, isCategory?: boolean) { | |
| const visual = thisOption.visual; | |
| const visualArr: VisualValue[] = []; | |
| if (zrUtil.isObject(visual)) { | |
| each(visual, function (v) { | |
| visualArr.push(v); | |
| }); | |
| } | |
| else if (visual != null) { | |
| visualArr.push(visual); | |
| } | |
| const doNotNeedPair = {color: 1, symbol: 1}; | |
| if (!isCategory | |
| && visualArr.length === 1 | |
| && !doNotNeedPair.hasOwnProperty(thisOption.type) | |
| ) { | |
| // Do not care visualArr.length === 0, which is illegal. | |
| visualArr[1] = visualArr[0]; | |
| } | |
| setVisualToOption(thisOption, visualArr); | |
| } | |
| function makePartialColorVisualHandler( | |
| applyValue: (prop: VisualValue, value: NormalizedValue) => VisualValue | |
| ): VisualHandler { | |
| return { | |
| applyVisual: function (value, getter, setter) { | |
| // Only used in HSL | |
| const colorChannel = this.mapValueToVisual(value); | |
| // Must not be array value | |
| setter('color', applyValue(getter('color'), colorChannel as number)); | |
| }, | |
| _normalizedToVisual: createNormalizedToNumericVisual([0, 1]) | |
| }; | |
| } | |
| function doMapToArray(this: VisualMapping, normalized: NormalizedValue): VisualValue { | |
| const visual = this.option.visual as VisualValue[]; | |
| return visual[ | |
| Math.round(linearMap(normalized, [0, 1], [0, visual.length - 1], true)) | |
| ] || {} as any; // TODO {}? | |
| } | |
| function makeApplyVisual(visualType: string): VisualHandler['applyVisual'] { | |
| return function (value, getter, setter) { | |
| setter(visualType, this.mapValueToVisual(value)); | |
| }; | |
| } | |
| function doMapCategory(this: VisualMapping, normalized: NormalizedValue): VisualValue { | |
| const visual = this.option.visual as Dictionary<any>; | |
| return visual[ | |
| (this.option.loop && normalized !== CATEGORY_DEFAULT_VISUAL_INDEX) | |
| ? normalized % visual.length | |
| : normalized | |
| ]; | |
| } | |
| function doMapFixed(this: VisualMapping): VisualValue { | |
| // visual will be convert to array. | |
| return (this.option.visual as VisualValue[])[0]; | |
| } | |
| /** | |
| * Create mapped to numeric visual | |
| */ | |
| function createNormalizedToNumericVisual(sourceExtent: [number, number]): VisualHandler['_normalizedToVisual'] { | |
| return { | |
| linear: function (normalized) { | |
| return linearMap(normalized, sourceExtent, this.option.visual as [number, number], true); | |
| }, | |
| category: doMapCategory, | |
| piecewise: function (normalized, value) { | |
| let result = getSpecifiedVisual.call(this, value); | |
| if (result == null) { | |
| result = linearMap(normalized, sourceExtent, this.option.visual as [number, number], true); | |
| } | |
| return result; | |
| }, | |
| fixed: doMapFixed | |
| }; | |
| } | |
| function getSpecifiedVisual(this: VisualMapping, value: number) { | |
| const thisOption = this.option; | |
| const pieceList = thisOption.pieceList; | |
| if (thisOption.hasSpecialVisual) { | |
| const pieceIndex = VisualMapping.findPieceIndex(value, pieceList); | |
| const piece = pieceList[pieceIndex]; | |
| if (piece && piece.visual) { | |
| return piece.visual[this.type]; | |
| } | |
| } | |
| } | |
| function setVisualToOption(thisOption: VisualMappingInnerOption, visualArr: VisualValue[]) { | |
| thisOption.visual = visualArr; | |
| if (thisOption.type === 'color') { | |
| thisOption.parsedVisual = zrUtil.map(visualArr, function (item: string) { | |
| const color = zrColor.parse(item); | |
| if (!color && __DEV__) { | |
| warn(`'${item}' is an illegal color, fallback to '#000000'`, true); | |
| } | |
| return color || [0, 0, 0, 1]; | |
| }); | |
| } | |
| return visualArr; | |
| } | |
| /** | |
| * Normalizers by mapping methods. | |
| */ | |
| const normalizers: { [key in MappingMethod]: Normalizer } = { | |
| linear: function (value: RawValue): NormalizedValue { | |
| return linearMap(value as number, this.option.dataExtent, [0, 1], true); | |
| }, | |
| piecewise: function (value: RawValue): NormalizedValue { | |
| const pieceList = this.option.pieceList; | |
| const pieceIndex = VisualMapping.findPieceIndex(value as number, pieceList, true); | |
| if (pieceIndex != null) { | |
| return linearMap(pieceIndex, [0, pieceList.length - 1], [0, 1], true); | |
| } | |
| }, | |
| category: function (value: RawValue): NormalizedValue { | |
| const index: number = this.option.categories | |
| ? this.option.categoryMap[value] | |
| : value as number; // ordinal value | |
| return index == null ? CATEGORY_DEFAULT_VISUAL_INDEX : index; | |
| }, | |
| fixed: zrUtil.noop as Normalizer | |
| }; | |
| function littleThan(close: boolean | 0 | 1, a: number, b: number): boolean { | |
| return close ? a <= b : a < b; | |
| } | |
| export default VisualMapping; | |