'use strict' ; import type AnimationOptions from '../../Animation/AnimationOptions' ; import type AxisLike from '../AxisLike' ; import type AxisOptions from '../AxisOptions' ; import type Chart from '../../Chart/Chart.js' ; import type ColorString from '../../Color/ColorString' ; import type ColorType from '../../Color/ColorType' ; import type Fx from '../../Animation/Fx' ; import type GradientColor from '../../Color/GradientColor' ; import type LegendOptions from '../../Legend/LegendOptions' ; import type Point from '../../Series/Point.js' ; import type PointerEvent from '../../PointerEvent' ; import type { StatesOptionsKey } from '../../Series/StatesOptions' ; import type SVGElement from '../../Renderer/SVG/SVGElement' ; import type SVGPath from '../../Renderer/SVG/SVGPath' ; import Axis from '../Axis.js' ; import Color from '../../Color/Color.js' ; const { parse : color } = Color ; import ColorAxisComposition from './ColorAxisComposition.js' ; import ColorAxisDefaults from './ColorAxisDefaults.js' ; import H from '../../Globals.js' ; const { noop } = H ; import Legend from '../../Legend/Legend.js' ; import LegendSymbol from '../../Legend/LegendSymbol.js' ; import SeriesRegistry from '../../Series/SeriesRegistry.js' ; const { series : Series } = SeriesRegistry ; import U from '../../Utilities.js' ; const { extend , isNumber , merge , pick } = U ; declare module '../../Axis/AxisLike' { interface AxisLike { labelLeft ? : number ; labelRight ? : number ; } } declare module '../../Chart/ChartLike' { interface ChartLike { colorAxis ? : Array < ColorAxis > ; } } declare module '../../../Core/Options' { interface Options { colorAxis ? : ( DeepPartial < ColorAxis . Options > | Array < DeepPartial < ColorAxis . Options > > ) ; } } declare module '../../Series/PointLike' { interface PointLike { dataClass ? : number ; } } declare module '../../Series/SeriesLike' { interface SeriesLike { axisTypes ? : Array < string > ; colorAxis ? : ColorAxis ; colorKey ? : string ; minColorValue ? : number ; maxColorValue ? : number ; } } declare module '../../Series/SeriesOptions' { interface SeriesOptions { colorKey ? : string ; } } class name augments Highcharts . Axis param { Highcharts . Chart } chart param { Highcharts . ColorAxisOptions } userOptions class ColorAxis extends Axis implements AxisLike { public static defaultColorAxisOptions = ColorAxisDefaults ; public static defaultLegendLength : number = 200 ; private public static keepProps : Array < string > = [ 'legendGroup' , 'legendItemHeight' , 'legendItemWidth' , 'legendItem' , 'legendSymbol' ] ; public static compose ( ChartClass , FxClass , LegendClass , SeriesClass ) { ColorAxisComposition . compose ( ColorAxis , ChartClass , FxClass , LegendClass , SeriesClass ) ; } private public constructor ( chart , userOptions ) { super ( chart , userOptions ) ; this . init ( chart , userOptions ) ; } public added ? : boolean ; public beforePadding = false as any ; public chart : Chart = void 0 as any ; public coll : 'colorAxis' = 'colorAxis' ; public dataClasses : Array < ColorAxis . DataClassesOptions > = void 0 as any ; public legendColor ? : GradientColor ; public legendGroup ? : SVGElement ; public legendItemHeight ? : number ; public legendItem : ColorAxis . LegendItemObject = void 0 as any ; public legendItems : Array < ColorAxis . LegendItemObject > = void 0 as any ; public legendItemWidth ? : number ; public legendSymbol ? : SVGElement ; public name : string = '' ; public options : ColorAxis . Options = void 0 as any ; public stops : GradientColor [ 'stops' ] = void 0 as any ; public visible : boolean = true ; function param { Highcharts . Chart } chart param { Highcharts . ColorAxisOptions } userOptions public init ( chart , userOptions ) { const axis = this ; const legend = chart . options . legend || { } , horiz = userOptions . layout ? userOptions . layout !== 'vertical' : legend . layout !== 'vertical' , visible = userOptions . visible ; const options = merge ( ColorAxis . defaultColorAxisOptions , userOptions , { showEmpty : false , title : null , visible : legend . enabled && visible !== false } ) ; axis . coll = 'colorAxis' ; axis . side = userOptions . side || horiz ? 2 : 1 ; axis . reversed = userOptions . reversed || ! horiz ; axis . opposite = ! horiz ; super . init ( chart , options ) ; axis . userOptions . visible = visible ; if ( userOptions . dataClasses ) { axis . initDataClasses ( userOptions ) ; } axis . initStops ( ) ; axis . horiz = horiz ; axis . zoomEnabled = false ; } private public initDataClasses ( userOptions ) { const axis = this , chart = axis . chart , options = axis . options , len = ( userOptions . dataClasses as any ) . length ; let dataClasses , colorCounter = 0 , colorCount = chart . options . chart . colorCount ; axis . dataClasses = dataClasses = [ ] as Array < ColorAxis . DataClassesOptions > ; axis . legendItems = [ ] as Array < ColorAxis . LegendItemObject > ; ( userOptions . dataClasses || [ ] ) . forEach ( function ( dataClass , i ) : void { let colors ; dataClass = merge ( dataClass ) ; dataClasses . push ( dataClass ) ; if ( ! chart . styledMode && dataClass . color ) { return ; } if ( options . dataClassColor === 'category' ) { if ( ! chart . styledMode ) { colors = chart . options . colors ; colorCount = colors . length ; dataClass . color = colors [ colorCounter ] ; } dataClass . colorIndex = colorCounter ; colorCounter ++ ; if ( colorCounter === colorCount ) { colorCounter = 0 ; } } else { dataClass . color = color ( options . minColor ) . tweenTo ( color ( options . maxColor ) , len < 2 ? 0.5 : i / ( len - 1 ) ) ; } } ) ; } function return { boolean } public hasData ( ) { return ! ! ( this . tickPositions || [ ] ) . length ; } private public setTickPositions ( ) { if ( ! this . dataClasses ) { return super . setTickPositions ( ) ; } } private public initStops ( ) { const axis = this ; axis . stops = axis . options . stops || [ [ 0 , axis . options . minColor as any ] , [ 1 , axis . options . maxColor as any ] ] ; axis . stops . forEach ( function ( stop ) : void { stop . color = color ( stop [ 1 ] ) ; } ) ; } private public setOptions ( userOptions ) { const axis = this ; super . setOptions ( userOptions ) ; axis . options . crosshair = axis . options . marker ; } private public setAxisSize ( ) { const axis = this ; const symbol = axis . legendSymbol ; const chart = axis . chart ; const legendOptions = chart . options . legend || { } ; let x , y , width , height ; if ( symbol ) { this . left = x = symbol . attr ( 'x' ) as any ; this . top = y = symbol . attr ( 'y' ) as any ; this . width = width = symbol . attr ( 'width' ) as any ; this . height = height = symbol . attr ( 'height' ) as any ; this . right = chart . chartWidth - x - width ; this . bottom = chart . chartHeight - y - height ; this . len = this . horiz ? width : height ; this . pos = this . horiz ? x : y ; } else { this . len = ( this . horiz ? legendOptions . symbolWidth : legendOptions . symbolHeight ) || ColorAxis . defaultLegendLength ; } } private public normalizedValue ( value ) { const axis = this ; if ( axis . logarithmic ) { value = axis . logarithmic . log2lin ( value ) ; } return 1 - ( ( ( axis . max as any ) - value ) / ( ( ( axis . max as any ) - ( axis . min as any ) ) || 1 ) ) ; } private public toColor ( value , point ) { const axis = this ; const dataClasses = axis . dataClasses ; const stops = axis . stops ; let pos , from , to , color , dataClass , i ; if ( dataClasses ) { i = dataClasses . length ; while ( i -- ) { dataClass = dataClasses [ i ] ; from = dataClass . from ; to = dataClass . to ; if ( ( typeof from === 'undefined' || value >= from ) && ( typeof to === 'undefined' || value <= to ) ) { color = dataClass . color as any ; if ( point ) { point . dataClass = i ; point . colorIndex = dataClass . colorIndex as any ; } break ; } } } else { pos = axis . normalizedValue ( value ) ; i = stops . length ; while ( i -- ) { if ( pos > stops [ i ] [ 0 ] ) { break ; } } from = stops [ i ] || stops [ i + 1 ] ; to = stops [ i + 1 ] || from ; pos = 1 - ( to [ 0 ] - pos ) / ( ( to [ 0 ] - from [ 0 ] ) || 1 ) ; color = ( from . color as any ) . tweenTo ( to . color , pos ) ; } return color ; } private public getOffset ( ) { const axis = this ; const group = axis . legendGroup ; const sideOffset = axis . chart . axisOffset [ axis . side ] ; if ( group ) { axis . axisParent = group ; super . getOffset ( ) ; const legend = this . chart . legend ; legend . allItems . forEach ( function ( item ) : void { if ( item instanceof ColorAxis ) { item . drawLegendSymbol ( legend , item ) ; } } ) ; legend . render ( ) ; this . chart . getMargins ( true ) ; if ( ! axis . added ) { axis . added = true ; axis . labelLeft = 0 ; axis . labelRight = axis . width ; } axis . chart . axisOffset [ axis . side ] = sideOffset ; } } private public setLegendColor ( ) { const axis = this ; const horiz = axis . horiz ; const reversed = axis . reversed ; const one = reversed ? 1 : 0 ; const zero = reversed ? 0 : 1 ; const grad = horiz ? [ one , 0 , zero , 0 ] : [ 0 , zero , 0 , one ] ; axis . legendColor = { linearGradient : { x1 : grad [ 0 ] , y1 : grad [ 1 ] , x2 : grad [ 2 ] , y2 : grad [ 3 ] } , stops : axis . stops } ; } private public drawLegendSymbol ( legend , item ) { const axis = this ; const padding = legend . padding ; const legendOptions = legend . options ; const horiz = axis . horiz ; const width = pick ( legendOptions . symbolWidth , horiz ? ColorAxis . defaultLegendLength : 12 ) ; const height = pick ( legendOptions . symbolHeight , horiz ? 12 : ColorAxis . defaultLegendLength ) ; const labelPadding = pick ( ( legendOptions as any ) . labelPadding , horiz ? 16 : 30 ) ; const itemDistance = pick ( legendOptions . itemDistance , 10 ) ; this . setLegendColor ( ) ; if ( ! item . legendSymbol ) { item . legendSymbol = this . chart . renderer . rect ( 0 , ( legend . baseline as any ) - 11 , width , height ) . attr ( { zIndex : 1 } ) . add ( item . legendGroup ) ; } axis . legendItemWidth = ( width + padding + ( horiz ? itemDistance : this . options . labels . x + this . maxLabelLength ) ) ; axis . legendItemHeight = height + padding + ( horiz ? labelPadding : 0 ) ; } private public setState ( state ? ) { this . series . forEach ( function ( series ) : void { series . setState ( state ) ; } ) ; } private public setVisible ( ) { } private public getSeriesExtremes ( ) { const axis = this ; const series = axis . series ; let colorValArray , colorKey , colorValIndex , pointArrayMap , calculatedExtremes , cSeries , i = series . length , yData , j ; this . dataMin = Infinity ; this . dataMax = - Infinity ; while ( i -- ) { cSeries = series [ i ] ; colorKey = cSeries . colorKey = pick ( cSeries . options . colorKey , cSeries . colorKey , cSeries . pointValKey , cSeries . zoneAxis , 'y' ) ; pointArrayMap = cSeries . pointArrayMap ; calculatedExtremes = ( cSeries as any ) [ colorKey + 'Min' ] && ( cSeries as any ) [ colorKey + 'Max' ] ; if ( ( cSeries as any ) [ colorKey + 'Data' ] ) { colorValArray = ( cSeries as any ) [ colorKey + 'Data' ] ; } else { if ( ! pointArrayMap ) { colorValArray = cSeries . yData ; } else { colorValArray = [ ] ; colorValIndex = pointArrayMap . indexOf ( colorKey ) ; yData = cSeries . yData ; if ( colorValIndex >= 0 && yData ) { for ( j = 0 ; j < yData . length ; j ++ ) { colorValArray . push ( pick ( ( yData [ j ] as any ) [ colorValIndex ] , yData [ j ] ) ) ; } } } } if ( calculatedExtremes ) { cSeries . minColorValue = ( cSeries as any ) [ colorKey + 'Min' ] ; cSeries . maxColorValue = ( cSeries as any ) [ colorKey + 'Max' ] ; } else { const cExtremes = Series . prototype . getExtremes . call ( cSeries , colorValArray ) ; cSeries . minColorValue = cExtremes . dataMin ; cSeries . maxColorValue = cExtremes . dataMax ; } if ( typeof cSeries . minColorValue !== 'undefined' ) { this . dataMin = Math . min ( this . dataMin , cSeries . minColorValue as any ) ; this . dataMax = Math . max ( this . dataMax , cSeries . maxColorValue as any ) ; } if ( ! calculatedExtremes ) { Series . prototype . applyExtremes . call ( cSeries ) ; } } } function param { Highcharts . PointerEventObject } e param { Highcharts . Point } point emits emits public drawCrosshair ( e ? , point ? ) { const axis = this ; const plotX = point && point . plotX ; const plotY = point && point . plotY ; const axisPos = axis . pos ; const axisLen = axis . len ; let crossPos ; if ( point ) { crossPos = axis . toPixels ( point . getNestedProperty ( point . series . colorKey ) as number ) ; if ( crossPos < ( axisPos as any ) ) { crossPos = ( axisPos as any ) - 2 ; } else if ( crossPos > ( axisPos as any ) + axisLen ) { crossPos = ( axisPos as any ) + axisLen + 2 ; } point . plotX = crossPos ; point . plotY = axis . len - crossPos ; super . drawCrosshair ( e , point ) ; point . plotX = plotX ; point . plotY = plotY ; if ( axis . cross && ! axis . cross . addedToColorAxis && axis . legendGroup ) { axis . cross . addClass ( 'highcharts-coloraxis-marker' ) . add ( axis . legendGroup ) ; axis . cross . addedToColorAxis = true ; if ( ! axis . chart . styledMode && typeof axis . crosshair === 'object' ) { axis . cross . attr ( { fill : axis . crosshair . color } ) ; } } } } private public getPlotLinePath ( options ) { const axis = this , left = axis . left , pos = options . translatedValue , top = axis . top ; return isNumber ( pos ) ? ( axis . horiz ? [ [ 'M' , pos - 4 , top - 6 ] , [ 'L' , pos + 4 , top - 6 ] , [ 'L' , pos , top ] , [ 'Z' ] ] : [ [ 'M' , left , pos ] , [ 'L' , left - 6 , pos + 6 ] , [ 'L' , left - 6 , pos - 6 ] , [ 'Z' ] ] ) : super . getPlotLinePath ( options ) ; } function param { Highcharts . ColorAxisOptions } newOptions param { boolean } redraw Whether to redraw the chart after the color axis is altered. If doing
     * more operations on the chart, it is a good idea to set redraw to `false`
     * and call  Highcharts . Chart after.
      public update ( newOptions , redraw ? ) { const axis = this , chart = axis . chart , legend = chart . legend ; this . series . forEach ( function ( series ) : void { series . isDirtyData = true ; } ) ; if ( newOptions . dataClasses && legend . allItems || axis . dataClasses ) { axis . destroyItems ( ) ; } super . update ( newOptions , redraw ) ; if ( axis . legendItem ) { axis . setLegendColor ( ) ; legend . colorizeItem ( this as any , true ) ; } } private public destroyItems ( ) { const axis = this ; const chart = axis . chart ; if ( axis . legendItem ) { chart . legend . destroyItem ( axis ) ; } else if ( axis . legendItems ) { axis . legendItems . forEach ( function ( item ) : void { chart . legend . destroyItem ( item as any ) ; } ) ; } chart . isDirtyLegend = true ; } public destroy ( ) { this . chart . isDirtyLegend = true ; this . destroyItems ( ) ; super . destroy ( ... [ ] . slice . call ( arguments ) ) ; } function param { boolean } redraw public remove ( redraw ? ) { this . destroyItems ( ) ; super . remove ( redraw ) ; } private public getDataClassLegendSymbols ( ) { const axis = this ; const chart = axis . chart ; const legendItems = axis . legendItems ; const legendOptions = chart . options . legend ; const valueDecimals = ( legendOptions as any ) . valueDecimals ; const valueSuffix = ( legendOptions as any ) . valueSuffix || '' ; let name ; if ( ! legendItems . length ) { axis . dataClasses . forEach ( ( dataClass , i ) : void => { const from = dataClass . from , to = dataClass . to , { numberFormatter } = chart ; let vis = true ; name = '' ; if ( typeof from === 'undefined' ) { name = '< ' ; } else if ( typeof to === 'undefined' ) { name = '> ' ; } if ( typeof from !== 'undefined' ) { name += numberFormatter ( from , valueDecimals ) + valueSuffix ; } if ( typeof from !== 'undefined' && typeof to !== 'undefined' ) { name += ' - ' ; } if ( typeof to !== 'undefined' ) { name += numberFormatter ( to , valueDecimals ) + valueSuffix ; } legendItems . push ( extend ( { chart : chart , name : name , options : { } , drawLegendSymbol : LegendSymbol . drawRectangle , visible : true , setState : noop , isDataClass : true , setVisible : function ( this ) : void { vis = axis . visible = ! vis ; axis . series . forEach ( function ( series ) : void { series . points . forEach ( function ( point ) : void { if ( point . dataClass === i ) { ( point as any ) . setVisible ( vis ) ; } } ) ; } ) ; chart . legend . colorizeItem ( this as any , vis ) ; } } , dataClass ) ) ; } ) ; } return legendItems ; } } namespace ColorAxis { export interface DataClassesOptions { color ? : ColorType ; colorIndex ? : number ; from ? : number ; name ? : string ; to ? : number ; } export interface LegendItemObject extends DataClassesOptions { [ key ] : any ; chart : Chart ; name : string ; options : object ; drawLegendSymbol : typeof LegendSymbol [ 'drawRectangle' ] ; visible : boolean ; setState : Function ; isDataClass : true ; setVisible : ( ) => void ; } export interface MarkerOptions { animation ? : ( boolean | Partial < AnimationOptions > ) ; color ? : ColorType ; width ? : number ; } export interface Options extends AxisOptions { dataClassColor ? : string ; dataClasses ? : Array < DataClassesOptions > ; layout ? : string ; legend ? : LegendOptions ; marker ? : MarkerOptions ; maxColor ? : ColorType ; minColor ? : ColorType ; showInLegend ? : boolean ; stops ? : GradientColor [ 'stops' ] ; } } Array . prototype . push . apply ( Axis . keepProps , ColorAxis . keepProps ) ; export default ColorAxis ; typedef { "linear" | "logarithmic" } Highcharts . ColorAxisTypeValue '' ;