@@ -224,8 +224,37 @@ const cellSize = computed(() => {
224224
225225const dataLabels = computed (() => {
226226 const yLabels = FINAL_CONFIG .value .style .layout .dataLabels .yAxis .values .length ? FINAL_CONFIG .value .style .layout .dataLabels .yAxis .values : props .dataset .map (ds => ds .name );
227- const xLabels = FINAL_CONFIG .value .style .layout .dataLabels .xAxis .values
227+ const xLabels = FINAL_CONFIG .value .style .layout .dataLabels .xAxis .values ;
228+ const _yTotals = props .dataset .map (ds => ds .values .reduce ((a , b ) => a + b, 0 ))
229+ const maxYTotal = Math .max (... _yTotals);
230+ const minYTotal = Math .min (... _yTotals);
231+
232+ const _xTotals = []
233+
234+ for (let i = 0 ; i < maxX .value ; i += 1 ) {
235+ _xTotals .push (props .dataset .map (ds => ds .values [i] || 0 ).reduce ((a , b ) => a + b, 0 ))
236+ }
237+
238+ const maxXTotal = Math .max (... _xTotals);
239+ const minXTotal = Math .min (... _xTotals);
240+
228241 return {
242+ yTotals: _yTotals .map (rowTotal => {
243+ const proportion = isNaN (rowTotal / maxYTotal) ? 0 : rowTotal / maxYTotal;
244+ return {
245+ total: rowTotal,
246+ proportion,
247+ color: interpolateColorHex (FINAL_CONFIG .value .style .layout .cells .colors .cold , FINAL_CONFIG .value .style .layout .cells .colors .hot , minYTotal, maxYTotal, rowTotal)
248+ }
249+ }),
250+ xTotals: _xTotals .map (columnTotal => {
251+ const proportion = isNaN (columnTotal / maxXTotal) ? 0 : columnTotal / maxXTotal;
252+ return {
253+ total: columnTotal,
254+ proportion,
255+ color: interpolateColorHex (FINAL_CONFIG .value .style .layout .cells .colors .cold , FINAL_CONFIG .value .style .layout .cells .colors .hot , minXTotal, maxXTotal, columnTotal)
256+ }
257+ }),
229258 yLabels,
230259 xLabels: xLabels .slice (0 , maxX .value )
231260 }
@@ -334,6 +363,34 @@ const bottomLegendIndicatorX = computed(() => {
334363 return drawingArea .value .left + ((svg .value .width - drawingArea .value .left - FINAL_CONFIG .value .style .layout .padding .right ) * (hoveredValue .value / maxValue .value ))
335364});
336365
366+ function getRowTotal (index ) {
367+ return applyDataLabel (
368+ FINAL_CONFIG .value .style .layout .cells .value .formatter ,
369+ dataLabels .value .yTotals [index].total ,
370+ dataLabel ({
371+ p: FINAL_CONFIG .value .style .layout .dataLabels .prefix ,
372+ v: dataLabels .value .yTotals [index].total ,
373+ s: FINAL_CONFIG .value .style .layout .dataLabels .suffix ,
374+ r: FINAL_CONFIG .value .style .layout .cells .value .roundingValue
375+ }),
376+ { datapoint: dataLabels .value .yTotals [index], rowIndex: index }
377+ )
378+ }
379+
380+ function getcolumnTotal (index ) {
381+ return applyDataLabel (
382+ FINAL_CONFIG .value .style .layout .cells .value .formatter ,
383+ dataLabels .value .xTotals [index].total ,
384+ dataLabel ({
385+ p: FINAL_CONFIG .value .style .layout .dataLabels .prefix ,
386+ v: dataLabels .value .xTotals [index].total ,
387+ s: FINAL_CONFIG .value .style .layout .dataLabels .suffix ,
388+ r: FINAL_CONFIG .value .style .layout .cells .value .roundingValue
389+ }),
390+ { datapoint: dataLabels .value .xTotals [index], colIndex: index }
391+ )
392+ }
393+
337394const table = computed (() => {
338395 const head = props .dataset .map (ds => {
339396 return {
@@ -387,6 +444,7 @@ function toggleAnnotator() {
387444 isAnnotator .value = ! isAnnotator .value ;
388445}
389446
447+
390448defineExpose ({
391449 generatePdf,
392450 generateCsv,
@@ -516,11 +574,34 @@ defineExpose({
516574 <slot name =" chart-background" />
517575 </foreignObject >
518576
577+ <template v-if =" FINAL_CONFIG .style .layout .cells .columnTotal .color .show " >
578+ <rect
579+ v-for =" (col, i) in dataLabels.xTotals"
580+ :x =" drawingArea.left + cellSize.width * i + (FINAL_CONFIG.style.layout.cells.spacing / 2) + (FINAL_CONFIG.style.layout.cells.rowTotal.color.show ? (cellSize.height / 3 + FINAL_CONFIG.style.layout.cells.spacing) : 0)"
581+ :y =" drawingArea.top - cellSize.height / 3 - FINAL_CONFIG.style.layout.cells.spacing"
582+ :height =" cellSize.height / 3"
583+ :width =" cellSize.width - FINAL_CONFIG.style.layout.cells.spacing"
584+ :fill =" FINAL_CONFIG.style.layout.cells.colors.underlayer"
585+ :stroke =" FINAL_CONFIG.style.backgroundColor"
586+ :stroke-width =" FINAL_CONFIG.style.layout.cells.spacing"
587+ />
588+ <rect
589+ v-for =" (col, i) in dataLabels.xTotals"
590+ :x =" drawingArea.left + cellSize.width * i + (FINAL_CONFIG.style.layout.cells.spacing / 2) + (FINAL_CONFIG.style.layout.cells.rowTotal.color.show ? (cellSize.height / 3 + FINAL_CONFIG.style.layout.cells.spacing) : 0)"
591+ :y =" drawingArea.top - cellSize.height / 3 - FINAL_CONFIG.style.layout.cells.spacing"
592+ :height =" cellSize.height / 3"
593+ :width =" cellSize.width - FINAL_CONFIG.style.layout.cells.spacing"
594+ :fill =" col.color"
595+ :stroke =" FINAL_CONFIG.style.backgroundColor"
596+ :stroke-width =" FINAL_CONFIG.style.layout.cells.spacing"
597+ />
598+ </template >
599+
519600 <g v-for =" (serie, i) in mutableDataset" >
520601 <g v-for =" (cell, j) in serie.temperatures" >
521602 <rect
522603 data-cy =" cell-underlayer"
523- :x =" drawingArea.left + cellSize.width * j + (FINAL_CONFIG.style.layout.cells.spacing / 2)"
604+ :x =" drawingArea.left + cellSize.width * j + (FINAL_CONFIG.style.layout.cells.spacing / 2) + (FINAL_CONFIG.style.layout.cells.rowTotal.color.show ? (cellSize.height / 3 + FINAL_CONFIG.style.layout.cells.spacing) : 0) "
524605 :y =" drawingArea.top + cellSize.height * i + (FINAL_CONFIG.style.layout.cells.spacing / 2)"
525606 :width =" cellSize.width - FINAL_CONFIG.style.layout.cells.spacing"
526607 :height =" cellSize.height - FINAL_CONFIG.style.layout.cells.spacing"
@@ -530,7 +611,7 @@ defineExpose({
530611 />
531612 <rect
532613 data-cy =" cell"
533- :x =" drawingArea.left + cellSize.width * j + (FINAL_CONFIG.style.layout.cells.spacing / 2)"
614+ :x =" drawingArea.left + cellSize.width * j + (FINAL_CONFIG.style.layout.cells.spacing / 2) + (FINAL_CONFIG.style.layout.cells.rowTotal.color.show ? (cellSize.height / 3 + FINAL_CONFIG.style.layout.cells.spacing) : 0) "
534615 :y =" drawingArea.top + cellSize.height * i + (FINAL_CONFIG.style.layout.cells.spacing / 2)"
535616 :width =" cellSize.width - FINAL_CONFIG.style.layout.cells.spacing"
536617 :height =" cellSize.height - FINAL_CONFIG.style.layout.cells.spacing"
@@ -545,7 +626,7 @@ defineExpose({
545626 :font-size =" FINAL_CONFIG.style.layout.cells.value.fontSize"
546627 :font-weight =" FINAL_CONFIG.style.layout.cells.value.bold ? 'bold': 'normal'"
547628 :fill =" adaptColorToBackground(cell.color)"
548- :x =" (drawingArea.left + cellSize.width * j) + (cellSize.width / 2)"
629+ :x =" (drawingArea.left + cellSize.width * j) + (cellSize.width / 2) + + (FINAL_CONFIG.style.layout.cells.rowTotal.color.show ? (cellSize.height / 3 + FINAL_CONFIG.style.layout.cells.spacing) : 0) "
549630 :y =" (drawingArea.top + cellSize.height * i) + (cellSize.height / 2) + FINAL_CONFIG.style.layout.cells.value.fontSize / 3"
550631 >
551632 {{ applyDataLabel(
@@ -566,7 +647,7 @@ defineExpose({
566647 <!-- TOOLTIP TRAPS -->
567648 <rect
568649 data-cy =" tooltip-trap"
569- :x =" drawingArea.left + cellSize.width * j"
650+ :x =" drawingArea.left + cellSize.width * j + (FINAL_CONFIG.style.layout.cells.rowTotal.color.show ? (cellSize.height / 3 + FINAL_CONFIG.style.layout.cells.spacing) : 0) "
570651 :y =" drawingArea.top + cellSize.height * i"
571652 :width =" cellSize.width"
572653 :height =" cellSize.height"
@@ -579,39 +660,90 @@ defineExpose({
579660 <g v-if =" FINAL_CONFIG.style.layout.dataLabels.yAxis.show" >
580661 <text
581662 data-cy =" axis-y-label"
663+ class =" vue-ui-heatmap-row-name"
582664 :font-size =" FINAL_CONFIG.style.layout.dataLabels.yAxis.fontSize"
583665 :fill =" FINAL_CONFIG.style.layout.dataLabels.yAxis.color"
584666 :x =" drawingArea.left + FINAL_CONFIG.style.layout.dataLabels.yAxis.offsetX - 6"
585- :y =" drawingArea.top + (cellSize.height * i) + cellSize.height / 2 + FINAL_CONFIG.style.layout.dataLabels.yAxis.fontSize / 3 + FINAL_CONFIG.style.layout.dataLabels.yAxis.offsetY"
667+ :y =" drawingArea.top + (cellSize.height * i) + cellSize.height / 2 + FINAL_CONFIG.style.layout.dataLabels.yAxis.fontSize / 3 + FINAL_CONFIG.style.layout.dataLabels.yAxis.offsetY - (FINAL_CONFIG.style.layout.cells.rowTotal.value.show ? FINAL_CONFIG.style.layout.dataLabels.yAxis.fontSize / 1.5 : 0) "
586668 text-anchor =" end"
587669 :font-weight =" FINAL_CONFIG.style.layout.dataLabels.yAxis.bold ? 'bold' : 'normal'"
588670 >
589671 {{ dataLabels.yLabels[i] }}
590672 </text >
673+ <text
674+ class =" vue-ui-heatmap-row-total"
675+ v-if =" FINAL_CONFIG.style.layout.cells.rowTotal.value.show"
676+ data-cy =" axis-y-label"
677+ :font-size =" FINAL_CONFIG.style.layout.dataLabels.yAxis.fontSize"
678+ :fill =" FINAL_CONFIG.style.layout.dataLabels.yAxis.color"
679+ :x =" drawingArea.left + FINAL_CONFIG.style.layout.dataLabels.yAxis.offsetX - 6"
680+ :y =" drawingArea.top + (cellSize.height * i) + cellSize.height / 2 + FINAL_CONFIG.style.layout.dataLabels.yAxis.fontSize + FINAL_CONFIG.style.layout.dataLabels.yAxis.offsetY"
681+ text-anchor =" end"
682+ :font-weight =" FINAL_CONFIG.style.layout.dataLabels.yAxis.bold ? 'bold' : 'normal'"
683+ >
684+ {{ getRowTotal(i) }}
685+ </text >
591686 </g >
687+
688+ <g v-if =" FINAL_CONFIG.style.layout.cells.rowTotal.color.show" >
689+ <rect
690+ :x =" drawingArea.left"
691+ :y =" drawingArea.top + (cellSize.height * i)"
692+ :width =" cellSize.height / 3"
693+ :height =" cellSize.height - FINAL_CONFIG.style.layout.cells.spacing"
694+ :fill =" FINAL_CONFIG.style.layout.cells.colors.underlayer"
695+ :stroke =" FINAL_CONFIG.style.backgroundColor"
696+ :stroke-width =" FINAL_CONFIG.style.layout.cells.spacing"
697+ />
698+ <rect
699+ :x =" drawingArea.left"
700+ :y =" drawingArea.top + (cellSize.height * i) + FINAL_CONFIG.style.layout.cells.spacing / 2"
701+ :width =" cellSize.height / 3"
702+ :height =" cellSize.height - FINAL_CONFIG.style.layout.cells.spacing"
703+ :fill =" dataLabels.yTotals[i].color"
704+ :stroke =" FINAL_CONFIG.style.backgroundColor"
705+ :stroke-width =" FINAL_CONFIG.style.layout.cells.spacing"
706+ />
707+ </g >
708+
592709 </g >
593710 <g v-if =" FINAL_CONFIG.style.layout.dataLabels.xAxis.show" >
594711 <template v-for =" (label , i ) in dataLabels .xLabels " >
595712 <text
713+ class =" vue-ui-heatmap-col-name"
596714 data-cy =" axis-x-label"
597715 v-if =" !FINAL_CONFIG.style.layout.dataLabels.xAxis.showOnlyAtModulo || (FINAL_CONFIG.style.layout.dataLabels.xAxis.showOnlyAtModulo && i % FINAL_CONFIG.style.layout.dataLabels.xAxis.showOnlyAtModulo === 0)"
598716 :text-anchor =" FINAL_CONFIG.style.layout.dataLabels.xAxis.rotation === 0 ? 'middle' : FINAL_CONFIG.style.layout.dataLabels.xAxis.rotation < 0 ? 'start' : 'end'"
599717 :font-size =" FINAL_CONFIG.style.layout.dataLabels.xAxis.fontSize"
600718 :fill =" FINAL_CONFIG.style.layout.dataLabels.xAxis.color"
601719 :font-weight =" FINAL_CONFIG.style.layout.dataLabels.xAxis.bold ? 'bold' : 'normal'"
602- :transform =" `translate(${drawingArea.left + cellSize.width / 2 + (drawingArea.width / dataLabels.xLabels.length * i) + FINAL_CONFIG.style.layout.dataLabels.xAxis.offsetX}, ${drawingArea.top + FINAL_CONFIG.style.layout.dataLabels.xAxis.offsetY - 6}), rotate(${FINAL_CONFIG.style.layout.dataLabels.xAxis.rotation})`"
720+ :transform =" `translate(${drawingArea.left + cellSize.width / 2 + (drawingArea.width / dataLabels.xLabels.length * i) + FINAL_CONFIG.style.layout.dataLabels.xAxis.offsetX + (FINAL_CONFIG.style.layout.cells.rowTotal.color.show ? (cellSize.height / 3 + FINAL_CONFIG.style.layout.cells.spacing) : 0) }, ${drawingArea.top + FINAL_CONFIG.style.layout.dataLabels.xAxis.offsetY - 6 - (FINAL_CONFIG.style.layout.cells.columnTotal.color.show ? (cellSize.height / 3 + FINAL_CONFIG.style.layout.cells.spacing) : 0) }), rotate(${FINAL_CONFIG.style.layout.dataLabels.xAxis.rotation})`"
603721 >
604722 {{ label }}
605723 </text >
606724 </template >
607725 </g >
608726
727+ <template v-if =" FINAL_CONFIG .style .layout .cells .columnTotal .value .show " >
728+ <text
729+ class =" vue-ui-heatmap-col-total"
730+ v-for =" (_, i) in dataLabels.xLabels"
731+ :text-anchor =" FINAL_CONFIG.style.layout.cells.columnTotal.value.rotation === 0 ? 'middle' : FINAL_CONFIG.style.layout.cells.columnTotal.value.rotation < 0 ? 'end' : 'start'"
732+ :font-size =" FINAL_CONFIG.style.layout.dataLabels.xAxis.fontSize"
733+ :fill =" FINAL_CONFIG.style.layout.dataLabels.xAxis.color"
734+ :font-weight =" FINAL_CONFIG.style.layout.dataLabels.xAxis.bold ? 'bold' : 'normal'"
735+ :transform =" `translate(${drawingArea.left + cellSize.width / 2 + (drawingArea.width / dataLabels.xLabels.length * i) + FINAL_CONFIG.style.layout.dataLabels.xAxis.offsetX + FINAL_CONFIG.style.layout.cells.columnTotal.value.offsetX + (FINAL_CONFIG.style.layout.cells.rowTotal.color.show ? (cellSize.height / 3 + FINAL_CONFIG.style.layout.cells.spacing) : 0)}, ${drawingArea.bottom - FINAL_CONFIG.style.layout.dataLabels.xAxis.fontSize + FINAL_CONFIG.style.layout.cells.columnTotal.value.offsetY}), rotate(${FINAL_CONFIG.style.layout.cells.columnTotal.value.rotation})`"
736+ >
737+ {{ getcolumnTotal(i) }}
738+ </text >
739+ </template >
740+
609741 <!-- BORDER FOR SELECTED RECT, PAINTED LAST -->
610742 <g v-if =" selectedClone" >
611743 <rect
612744 data-cy =" cell-selected"
613745 style =" pointer-events : none ;"
614- :x =" selectedClone.x - ((FINAL_CONFIG.style.layout.cells.selected.border) / 2) + FINAL_CONFIG.style.layout.cells.spacing"
746+ :x =" selectedClone.x - ((FINAL_CONFIG.style.layout.cells.selected.border) / 2) + FINAL_CONFIG.style.layout.cells.spacing + (FINAL_CONFIG.style.layout.cells.rowTotal.color.show ? (cellSize.height / 3 + FINAL_CONFIG.style.layout.cells.spacing) : 0) "
615747 :y =" selectedClone.y - (FINAL_CONFIG.style.layout.cells.selected.border / 2) + FINAL_CONFIG.style.layout.cells.spacing"
616748 :width =" cellSize.width - FINAL_CONFIG.style.layout.cells.spacing + FINAL_CONFIG.style.layout.cells.selected.border - (FINAL_CONFIG.style.layout.cells.spacing)"
617749 :height =" cellSize.height - FINAL_CONFIG.style.layout.cells.spacing + FINAL_CONFIG.style.layout.cells.selected.border - (FINAL_CONFIG.style.layout.cells.spacing)"
0 commit comments