fileOverview import React , { PureComponent , ReactElement , SVGProps } from 'react' ; import _ from 'lodash' ; import { isNumber } from '../util/DataUtils' ; import { ChartOffset , D3Scale , filterProps } from '../util/types' ; import { Props as XAxisProps } from './XAxis' ; import { Props as YAxisProps } from './YAxis' ; type GridLineType = SVGProps < SVGLineElement > | ReactElement < SVGElement > | ( ( props : any ) => ReactElement < SVGElement > ) | boolean ; interface IntrnalCartesianGridProps { x ? : number ; y ? : number ; width ? : number ; height ? : number ; horizontalCoordinatesGenerator ? : ( props : any ) => number [ ] ; verticalCoordinatesGenerator ? : ( props : any ) => number [ ] ; xAxis ? : Omit < XAxisProps , 'scale' > & { scale : D3Scale < string | number > ; } ; yAxis ? : Omit < YAxisProps , 'scale' > & { scale : D3Scale < string | number > ; } ; offset ? : ChartOffset ; chartWidth ? : number ; chartHeight ? : number ; } interface CartesianGridProps extends IntrnalCartesianGridProps { horizontal ? : GridLineType ; vertical ? : GridLineType ; horizontalPoints ? : number [ ] ; verticalPoints ? : number [ ] ; verticalFill ? : string [ ] ; horizontalFill ? : string [ ] ; } export type Props = SVGProps < SVGElement > & CartesianGridProps ; export class CartesianGrid extends PureComponent < Props > { static displayName = 'CartesianGrid' ; static defaultProps = { horizontal : true , vertical : true , horizontalPoints : [ ] as CartesianGridProps [ 'horizontalPoints' ] , verticalPoints : [ ] as CartesianGridProps [ 'verticalPoints' ] , stroke : '#ccc' , fill : 'none' , verticalFill : [ ] as CartesianGridProps [ 'verticalFill' ] , horizontalFill : [ ] as CartesianGridProps [ 'horizontalFill' ] , } ; static renderLineItem ( option , props ) { let lineItem ; if ( React . isValidElement ( option ) ) { lineItem = React . cloneElement ( option , props ) ; } else if ( _ . isFunction ( option ) ) { lineItem = option ( props ) ; } else { const { x1 , y1 , x2 , y2 , key , ... others } = props ; lineItem = < line { ... filterProps ( others ) } x1 = { x1 } y1 = { y1 } x2 = { x2 } y2 = { y2 } fill = "none" key = { key } / > ; } return lineItem ; } param { Array } horizontalPoints return { Group } renderHorizontal ( horizontalPoints ) { const { x , width , horizontal } = this . props ; if ( ! horizontalPoints || ! horizontalPoints . length ) { return null ; } const items = horizontalPoints . map ( ( entry , i ) => { const props = { ... this . props , x1 : x , y1 : entry , x2 : x + width , y2 : entry , key : `line-${ i }` , index : i , } ; return CartesianGrid . renderLineItem ( horizontal , props ) ; } ) ; return < g className = "recharts-cartesian-grid-horizontal" > { items } < /g>; } param { Array } verticalPoints return { Group } renderVertical ( verticalPoints ) { const { y , height , vertical } = this . props ; if ( ! verticalPoints || ! verticalPoints . length ) { return null ; } const items = verticalPoints . map ( ( entry , i ) => { const props = { ... this . props , x1 : entry , y1 : y , x2 : entry , y2 : y + height , key : `line-${ i }` , index : i , } ; return CartesianGrid . renderLineItem ( vertical , props ) ; } ) ; return < g className = "recharts-cartesian-grid-vertical" > { items } < /g>; } param { Array } verticalPoints return { Group } renderVerticalStripes ( verticalPoints ) { const { verticalFill } = this . props ; if ( ! verticalFill || ! verticalFill . length ) { return null ; } const { fillOpacity , x , y , width , height } = this . props ; const verticalPointsUpdated = verticalPoints . slice ( ) . sort ( ( a , b ) => a - b ) ; if ( x !== verticalPointsUpdated [ 0 ] ) { verticalPointsUpdated . unshift ( 0 ) ; } const items = verticalPointsUpdated . map ( ( entry , i ) => { const lineWidth = verticalPointsUpdated [ i + 1 ] ? verticalPointsUpdated [ i + 1 ] - entry : x + width - entry ; if ( lineWidth <= 0 ) { return null ; } const colorIndex = i % verticalFill . length ; return ( < rect key = { `react-${ i }` } x = { Math . round ( entry + x - x ) } y = { y } width = { lineWidth } height = { height } stroke = "none" fill = { verticalFill [ colorIndex ] } fillOpacity = { fillOpacity } className = "recharts-cartesian-grid-bg" / > ) ; } ) ; return < g className = "recharts-cartesian-gridstripes-vertical" > { items } < /g>; } param { Array } horizontalPoints return { Group } renderHorizontalStripes ( horizontalPoints ) { const { horizontalFill } = this . props ; if ( ! horizontalFill || ! horizontalFill . length ) { return null ; } const { fillOpacity , x , y , width , height } = this . props ; const horizontalPointsUpdated = horizontalPoints . slice ( ) . sort ( ( a , b ) => a - b ) ; if ( y !== horizontalPointsUpdated [ 0 ] ) { horizontalPointsUpdated . unshift ( 0 ) ; } const items = horizontalPointsUpdated . map ( ( entry , i ) => { const lineHeight = horizontalPointsUpdated [ i + 1 ] ? horizontalPointsUpdated [ i + 1 ] - entry : y + height - entry ; if ( lineHeight <= 0 ) { return null ; } const colorIndex = i % horizontalFill . length ; return ( < rect key = { `react-${ i }` } y = { Math . round ( entry + y - y ) } x = { x } height = { lineHeight } width = { width } stroke = "none" fill = { horizontalFill [ colorIndex ] } fillOpacity = { fillOpacity } className = "recharts-cartesian-grid-bg" / > ) ; } ) ; return < g className = "recharts-cartesian-gridstripes-horizontal" > { items } < /g>; } renderBackground ( ) { const { fill } = this . props ; if ( ! fill || fill === 'none' ) { return null ; } const { fillOpacity , x , y , width , height } = this . props ; return ( < rect x = { x } y = { y } width = { width } height = { height } stroke = "none" fill = { fill } fillOpacity = { fillOpacity } className = "recharts-cartesian-grid-bg" / > ) ; } render ( ) { const { x , y , width , height , horizontal , vertical , horizontalCoordinatesGenerator , verticalCoordinatesGenerator , xAxis , yAxis , offset , chartWidth , chartHeight , } = this . props ; if ( ! isNumber ( width ) || width <= 0 || ! isNumber ( height ) || height <= 0 || ! isNumber ( x ) || x !== + x || ! isNumber ( y ) || y !== + y ) { return null ; } let { horizontalPoints , verticalPoints } = this . props ; if ( ( ! horizontalPoints || ! horizontalPoints . length ) && _ . isFunction ( horizontalCoordinatesGenerator ) ) { horizontalPoints = horizontalCoordinatesGenerator ( { yAxis , width : chartWidth , height : chartHeight , offset } ) ; } if ( ( ! verticalPoints || ! verticalPoints . length ) && _ . isFunction ( verticalCoordinatesGenerator ) ) { verticalPoints = verticalCoordinatesGenerator ( { xAxis , width : chartWidth , height : chartHeight , offset } ) ; } return ( < g className = "recharts-cartesian-grid" > { this . renderBackground ( ) } { horizontal && this . renderHorizontal ( horizontalPoints ) } { vertical && this . renderVertical ( verticalPoints ) } { horizontal && this . renderHorizontalStripes ( horizontalPoints ) } { vertical && this . renderVerticalStripes ( verticalPoints ) } < /g>); } }