import { scaleLinear , scaleOrdinal } from 'd3-scale' ; import { schemeCategory10 } from 'd3-scale-chromatic' ; import _ from 'lodash' ; enum ScaleType { LINEAR = 'linear' , ORDINAL = 'ordinal' } export interface ColorScaleInfo { id : string ; label : string ; type : ScaleType ; contrastColor : string ; domain : number [ ] ; range : string [ ] ; } export const redGreen = { id : 'red-green' , label : 'Red-Green' , type : ScaleType . LINEAR , contrastColor : 'white' , domain : [ .0 , .5 , 1.0 ] , range : [ 'red' , '#333' , 'green' ] } ; export const CWYR = { id : 'cwyr' , label : 'CWYR' , type : ScaleType . LINEAR , contrastColor : 'black' , domain : [ .0 , .25 , .5 , .75 , 1.0 ] , range : [ 'cyan' , '#d5e9f0' , 'white' , 'yellow' , 'red' ] } ; export const monochrome = { id : 'monochrome' , label : 'Monochrome' , type : ScaleType . LINEAR , contrastColor : 'white' , domain : [ .0 , 1.0 ] , range : [ 'black' , 'white' ] } ; export const redYellow = { id : 'red-yellow' , label : 'Red-Yellow' , type : ScaleType . LINEAR , contrastColor : 'black' , domain : [ .0 , .5 , 1.0 ] , range : [ 'red' , '#333' , 'yellow' ] } ; export const yellowBlue = { id : 'yellow-blue' , label : 'Yellow-Blue' , type : ScaleType . LINEAR , contrastColor : 'black' , domain : [ 0.0 , 0.5 , 1.0 ] , range : [ 'yellow' , '#333' , 'blue' ] } ; export const categorical = { id : 'categorical' , label : 'Categorical' , type : ScaleType . ORDINAL , contrastColor : 'white' , domain : _ . range ( 10 ) , range : schemeCategory10 as string [ ] } ; export const allColorScaleInfo = [ redGreen , CWYR , monochrome , redYellow , yellowBlue , categorical , ] ; const findColorScale = ( id ) : ColorScaleInfo => { const scale = allColorScaleInfo . find ( info => info . id === id ) ; if ( ! scale ) { console . error ( `color scale ${ id } not found` ) ; } return scale as ColorScaleInfo ; } ; type ColorScaleCallable = ( value : number | string ) => string ; export const getColorScale = ( id ) : ColorScaleCallable => { const scale = findColorScale ( id ) ; if ( scale . type === ScaleType . LINEAR ) { return scaleLinear < string , string > ( ) . domain ( scale . domain ) . range ( scale . range ) as ColorScaleCallable ; } else { return scaleOrdinal < number , string > ( ) . domain ( scale . domain ) . range ( scale . range ) as ColorScaleCallable ; } } ; export const getColorScaleGradient = ( id ) : string => { const scale = findColorScale ( id ) ; let gradient = 'linear-gradient(to right,' ; if ( scale . type === ScaleType . LINEAR ) { gradient += scale . range . join ( ',' ) ; } else { gradient += scale . range . map ( ( val , index ) => { return val + ' ' + ( index * 100 / scale . range . length ) + '%,' + val + ' ' + ( ( index + 1 ) * 100 / scale . range . length ) + '%' ; } ) . join ( ',' ) ; } gradient += ')' ; return gradient ; } ;