@@ -4,22 +4,23 @@ import { autoBandwidth, extentLinear, seriesSvgBar } from 'd3fc';
44interface HeatMapChartProps {
55 title : string ;
66 data : number [ ] [ ] ;
7+ columns : string [ ] ;
78}
89
910// Define margins for the chart
1011const margin = { top : 10 , right : 0 , bottom : 40 , left : 0 } ;
1112// Define height for the chart, adjusting for margins
1213const height = 300 - margin . top - margin . bottom ;
1314
14- const HeatMapChart = ( { title, data } : HeatMapChartProps ) => {
15+ const HeatMapChart = ( { title, data, columns } : HeatMapChartProps ) => {
1516 const svgRef = useRef ( null ) ; // Reference to the SVG element
1617 const containerRef = useRef ( null ) ; // Reference to the container div
1718 const [ containerWidth , setContainerWidth ] = useState ( 800 ) ; // Default container width
1819
1920 useEffect ( ( ) => {
2021 // Clear any previous SVG content to avoid overlapping elements
2122 d3 . select ( svgRef . current ) . selectAll ( '*' ) . remove ( ) ;
22- const legendWidth = 100 ;
23+ const legendWidth = 150 ;
2324 const widthForHeatmap = containerWidth - 50 - legendWidth ;
2425 const barWidth = Math . max (
2526 10 ,
@@ -73,6 +74,25 @@ const HeatMapChart = ({ title, data }: HeatMapChartProps) => {
7374 . style ( 'fill' , function ( ) {
7475 return colorScale ( dataCell ) ;
7576 } ) ;
77+
78+ const color = d3 . color ( colorScale ( dataCell ) ) ;
79+ if ( ! color ) return 'black' ;
80+
81+ // Get RGB values using d3.rgb() ..
82+ const rgb = d3 . rgb ( color ) ;
83+
84+ // Calculate perceived brightness
85+ const luminance =
86+ ( 0.299 * rgb . r + 0.587 * rgb . g + 0.114 * rgb . b ) / 255 ;
87+ const textColor = luminance < 0.5 ? 'white' : 'black' ;
88+ svg . append ( 'text' )
89+ . attr ( 'x' , barWidth / 2 + 50 + cellIndex * barWidth )
90+ . attr ( 'y' , barHeight / 2 + rowIndex * barHeight )
91+ . attr ( 'text-anchor' , 'middle' )
92+ . attr ( 'dominant-baseline' , 'middle' )
93+ . style ( 'fill' , textColor )
94+ . style ( 'font-size' , '10px' )
95+ . text ( dataCell . toFixed ( 2 ) ) ;
7696 } ) ;
7797 } ) ;
7898
@@ -81,10 +101,10 @@ const HeatMapChart = ({ title, data }: HeatMapChartProps) => {
81101 . data ( data [ 0 ] )
82102 . join ( 'text' )
83103 . attr ( 'x' , ( _ , i ) => 50 + i * barWidth + barWidth / 2 )
84- . attr ( 'y' , 50 + barHeight * data . length )
104+ . attr ( 'y' , 20 + barHeight * data . length )
85105 . attr ( 'text-anchor' , 'middle' )
86106 . style ( 'font-size' , '12px' )
87- . text ( ( _ , i ) => `Cell ${ i + 1 } ` ) ;
107+ . text ( ( _ , i ) => `${ columns ?. [ i ] } ` ) ;
88108
89109 svg . append ( 'g' )
90110 . selectAll ( 'text' )
@@ -95,7 +115,7 @@ const HeatMapChart = ({ title, data }: HeatMapChartProps) => {
95115 . attr ( 'dy' , '0.35em' )
96116 . attr ( 'text-anchor' , 'end' )
97117 . style ( 'font-size' , '12px' )
98- . text ( ( _ , i ) => `Row ${ i + 1 } ` ) ;
118+ . text ( ( _ , i ) => `${ columns ?. [ i ] } ` ) ;
99119
100120 const svgBar = autoBandwidth ( seriesSvgBar ( ) )
101121 . xScale ( xScale )
@@ -130,7 +150,7 @@ const HeatMapChart = ({ title, data }: HeatMapChartProps) => {
130150 const legendBar = svg . append ( 'g' ) . datum ( expandedDomain ) . call ( svgBar ) ;
131151 legendBar . attr (
132152 'transform' ,
133- `translate(${ legendWidth + barWidth * data . length } ,0)`
153+ `translate(${ legendWidth - 50 + barWidth * data . length } ,0)`
134154 ) ;
135155 const legendBarWidth = Math . abs (
136156 legendBar . node ( ) ! . getBoundingClientRect ( ) . x
0 commit comments