@@ -238,7 +238,12 @@ function refreshSlicer() {
238238}
239239
240240const barSlot = computed (() => {
241- const bs = drawingArea .value .width / (slicer .value .end - slicer .value .start );
241+ let bs;
242+ if (FINAL_CONFIG .value .orientation === ' vertical' ) {
243+ bs = drawingArea .value .width / (slicer .value .end - slicer .value .start );
244+ } else {
245+ bs = drawingArea .value .height / (slicer .value .end - slicer .value .start );
246+ }
242247 return bs <= 0 ? 0 : bs;
243248});
244249
@@ -285,6 +290,9 @@ const yLabels = computed(() => {
285290 zero: drawingArea .value .bottom - (drawingArea .value .height * ((Math .abs (scale .min )) / (scale .max + Math .abs (scale .min )))),
286291 y: drawingArea .value .bottom - (drawingArea .value .height * ((t + Math .abs (scale .min )) / ((scale .max ) + Math .abs (scale .min )))),
287292 x: drawingArea .value .left - 8 ,
293+ horizontal_zero: drawingArea .value .left + (drawingArea .value .width * ((Math .abs (scale .min )) / (scale .max + Math .abs (scale .min )))),
294+ horizontal_x: drawingArea .value .left + (drawingArea .value .width * ((t + Math .abs (scale .min )) / ((scale .max ) + Math .abs (scale .min )))),
295+ horizontal_y: drawingArea .value .bottom - 8 ,
288296 value: t
289297 }
290298 });
@@ -299,7 +307,9 @@ const formattedDataset = computed(() => {
299307 if (! isDataset .value ) return [];
300308
301309 let cumulativeY = Array (maxSeries .value ).fill (0 );
310+ let cumulativeX = Array (maxSeries .value ).fill (0 );
302311 let cumulativeNegY = Array (maxSeries .value ).fill (0 );
312+ let cumulativeNegX = Array (maxSeries .value ).fill (0 );
303313
304314 const premax = Math .max (... datasetSignedTotals .value .positive ) || 0 ;
305315 const workingMin = Math .min (... datasetSignedTotals .value .negative );
@@ -311,7 +321,9 @@ const formattedDataset = computed(() => {
311321 const maxTotal = (MAX + (MIN >= 0 ? 0 : Math .abs (MIN ))) || 1
312322
313323 const totalHeight = drawingArea .value .height ;
324+ const totalWidth = drawingArea .value .width ;
314325 const ZERO_POSITION = yLabels .value [0 ] ? yLabels .value [0 ].zero : drawingArea .value .bottom ;
326+ const HORIZONTAL_ZERO_POSITION = yLabels .value [0 ] ? yLabels .value [0 ].horizontal_zero : drawingArea .value .left ;
315327
316328 return unmutableDataset .value
317329 .filter (ds => ! segregated .value .includes (ds .id ))
@@ -323,6 +335,10 @@ const formattedDataset = computed(() => {
323335 return drawingArea .value .left + (barSlot .value * i) + (barSlot .value * FINAL_CONFIG .value .style .chart .bars .gapRatio / 4 );
324336 });
325337
338+ const horizontal_y = slicedSeries .map ((_dp , i ) => {
339+ return drawingArea .value .top + (barSlot .value * i) + (barSlot .value * FINAL_CONFIG .value .style .chart .bars .gapRatio / 4 );
340+ })
341+
326342 const y = slicedSeries .map ((dp , i ) => {
327343 const proportion = FINAL_CONFIG .value .style .chart .bars .distributed
328344 ? (dp || 0 ) / datasetTotals .value [i]
@@ -341,6 +357,24 @@ const formattedDataset = computed(() => {
341357 return currentY;
342358 });
343359
360+ const horizontal_x = slicedSeries .map ((dp , i ) => {
361+ const proportion = FINAL_CONFIG .value .style .chart .bars .distributed
362+ ? (dp || 0 ) / datasetTotals .value [i]
363+ : (dp || 0 ) / maxTotal;
364+
365+ let currentX, hw;
366+ if (dp > 0 ) {
367+ hw = totalWidth * proportion;
368+ currentX = HORIZONTAL_ZERO_POSITION + cumulativeX[i];
369+ cumulativeX[i] += hw;
370+ } else {
371+ hw = totalWidth * proportion;
372+ currentX = HORIZONTAL_ZERO_POSITION - Math .abs (hw) - cumulativeNegX[i]
373+ cumulativeNegX[i] += Math .abs (hw)
374+ }
375+ return currentX;
376+ });
377+
344378 const height = slicedSeries .map ((dp , i ) => {
345379 const proportion = FINAL_CONFIG .value .style .chart .bars .distributed
346380 ? (dp || 0 ) / datasetTotals .value [i]
@@ -353,6 +387,18 @@ const formattedDataset = computed(() => {
353387 }
354388 });
355389
390+ const horizontal_width = slicedSeries .map ((dp , i ) => {
391+ const proportion = FINAL_CONFIG .value .style .chart .bars .distributed
392+ ? (dp || 0 ) / datasetTotals .value [i]
393+ : (dp || 0 ) / maxTotal;
394+
395+ if (dp > 0 ) {
396+ return totalWidth * proportion
397+ } else {
398+ return totalWidth * Math .abs (proportion)
399+ }
400+ });
401+
356402 const absoluteTotal = slicedSeries .map (v => Math .abs (v)).reduce ((a , b ) => a + b, 0 );
357403
358404 return {
@@ -369,6 +415,9 @@ const formattedDataset = computed(() => {
369415 x,
370416 y,
371417 height,
418+ horizontal_width,
419+ horizontal_y,
420+ horizontal_x
372421 };
373422 });
374423});
@@ -719,7 +768,8 @@ defineExpose({
719768 < / linearGradient>
720769 < / defs>
721770
722- < template v- if = " FINAL_CONFIG.style.chart.grid.x.showHorizontalLines" >
771+ <!-- HORIZONTAL LINES (vertical mode) -->
772+ < template v- if = " FINAL_CONFIG.style.chart.grid.x.showHorizontalLines && FINAL_CONFIG.orientation === 'vertical'" >
723773 < line
724774 v- for = " (yLabel, i) in yLabels"
725775 : x1= " drawingArea.left"
@@ -728,10 +778,26 @@ defineExpose({
728778 : y2= " yLabel.y"
729779 : stroke= " FINAL_CONFIG.style.chart.grid.x.axisColor"
730780 : stroke- width= " 1"
781+ stroke- linecap= " round"
782+ / >
783+ < / template>
784+
785+ <!-- HORIZONTAL LINES (horizontal mode) -->
786+ < template v- if = " FINAL_CONFIG.style.chart.grid.x.showHorizontalLines && FINAL_CONFIG.orientation === 'horizontal'" >
787+ < line
788+ v- for = " (_, i) in (slicer.end - slicer.start + 1)"
789+ : x1= " drawingArea.left"
790+ : x2= " drawingArea.right"
791+ : y1= " drawingArea.top + (barSlot * i)"
792+ : y2= " drawingArea.top + (barSlot * i)"
793+ : stroke= " FINAL_CONFIG.style.chart.grid.y.axisColor"
794+ : stroke- width= " 1"
795+ stroke- linecap= " round"
731796 / >
732797 < / template>
733798
734- < template v- if = " FINAL_CONFIG.style.chart.grid.y.showVerticalLines" >
799+ <!-- VERTICAL LINES (vertical mode) -->
800+ < template v- if = " FINAL_CONFIG.style.chart.grid.y.showVerticalLines && FINAL_CONFIG.orientation === 'vertical'" >
735801 < line
736802 v- for = " (_, i) in (slicer.end - slicer.start + 1)"
737803 : x1= " drawingArea.left + (barSlot * i)"
@@ -740,25 +806,60 @@ defineExpose({
740806 : y2= " drawingArea.bottom"
741807 : stroke= " FINAL_CONFIG.style.chart.grid.y.axisColor"
742808 : stroke- width= " 1"
809+ stroke- linecap= " round"
743810 / >
744811 < / template>
745812
746- <!-- STACKED BARS -->
747- < g v- for = " (dp, i) in formattedDataset" >
748- < rect
749- v- for = " (rect, j) in dp.x"
750- : x= " rect"
751- : y= " dp.y[j] < 0 ? 0 : dp.y[j]"
752- : height= " dp.height[j] < 0 ? 0.0001 : dp.height[j]"
753- : rx= " FINAL_CONFIG.style.chart.bars.borderRadius > dp.height[j] / 2 ? (dp.height[j] < 0 ? 0 : dp.height[j]) / 2 : FINAL_CONFIG.style.chart.bars.borderRadius "
754- : width= " barSlot * (1 - FINAL_CONFIG.style.chart.bars.gapRatio / 2)"
755- : fill= " FINAL_CONFIG.style.chart.bars.gradient.show ? `url(#gradient_${dp.id})` : dp.color"
756- : stroke= " FINAL_CONFIG.style.chart.backgroundColor"
757- : stroke- width= " FINAL_CONFIG.style.chart.bars.strokeWidth"
813+ <!-- VERTICAL LINES (horizontal mode) -->
814+ < template v- if = " FINAL_CONFIG.style.chart.grid.x.showHorizontalLines && FINAL_CONFIG.orientation === 'horizontal'" >
815+ < line
816+ v- for = " (yLabel, i) in yLabels"
817+ : x1= " yLabel.horizontal_x"
818+ : x2= " yLabel.horizontal_x"
819+ : y1= " drawingArea.top"
820+ : y2= " drawingArea.bottom"
821+ : stroke= " FINAL_CONFIG.style.chart.grid.x.axisColor"
822+ : stroke- width= " 1"
758823 stroke- linecap= " round"
759- stroke- linejoin= " round"
760- : class = " { 'vue-data-ui-bar-animated': FINAL_CONFIG.useCssAnimation, 'vue-data-ui-bar-transition': isLoaded }"
761- / >
824+ / >
825+ < / template>
826+
827+ < g v- for = " (dp, i) in formattedDataset" >
828+ <!-- STACKED BARS (vertical mode) -->
829+ < template v- if = " FINAL_CONFIG.orientation === 'vertical'" >
830+ < rect
831+ v- for = " (rect, j) in dp.x"
832+ : x= " rect"
833+ : y= " dp.y[j] < 0 ? 0 : dp.y[j]"
834+ : height= " dp.height[j] < 0 ? 0.0001 : dp.height[j]"
835+ : rx= " FINAL_CONFIG.style.chart.bars.borderRadius > dp.height[j] / 2 ? (dp.height[j] < 0 ? 0 : dp.height[j]) / 2 : FINAL_CONFIG.style.chart.bars.borderRadius "
836+ : width= " barSlot * (1 - FINAL_CONFIG.style.chart.bars.gapRatio / 2)"
837+ : fill= " FINAL_CONFIG.style.chart.bars.gradient.show ? `url(#gradient_${dp.id})` : dp.color"
838+ : stroke= " FINAL_CONFIG.style.chart.backgroundColor"
839+ : stroke- width= " FINAL_CONFIG.style.chart.bars.strokeWidth"
840+ stroke- linecap= " round"
841+ stroke- linejoin= " round"
842+ : class = " { 'vue-data-ui-bar-animated': FINAL_CONFIG.useCssAnimation, 'vue-data-ui-bar-transition': isLoaded }"
843+ / >
844+ < / template>
845+
846+ <!-- STACKED BARS (horizontal mode) -->
847+ < template v- else >
848+ < rect
849+ v- for = " (rect, j) in dp.horizontal_x"
850+ : x= " rect"
851+ : y= " dp.horizontal_y[j] < 0 ? 0 : dp.horizontal_y[j]"
852+ : width= " dp.horizontal_width[j] < 0 ? 0.0001 : dp.horizontal_width[j]"
853+ : rx= " FINAL_CONFIG.style.chart.bars.borderRadius > dp.height[j] / 2 ? (dp.height[j] < 0 ? 0 : dp.height[j]) / 2 : FINAL_CONFIG.style.chart.bars.borderRadius "
854+ : height= " barSlot * (1 - FINAL_CONFIG.style.chart.bars.gapRatio / 2)"
855+ : fill= " FINAL_CONFIG.style.chart.bars.gradient.show ? `url(#gradient_${dp.id})` : dp.color"
856+ : stroke= " FINAL_CONFIG.style.chart.backgroundColor"
857+ : stroke- width= " FINAL_CONFIG.style.chart.bars.strokeWidth"
858+ stroke- linecap= " round"
859+ stroke- linejoin= " round"
860+ : class = " { 'vue-data-ui-bar-animated': FINAL_CONFIG.useCssAnimation, 'vue-data-ui-bar-transition': isLoaded }"
861+ / >
862+ < / template>
762863 < / g>
763864
764865 <!-- X AXIS -->
@@ -812,7 +913,8 @@ defineExpose({
812913 {{ FINAL_CONFIG .style .chart .grid .y .axisName .text }}
813914 < / text>
814915
815- < template v- if = " mutableConfig.dataLabels.show" >
916+ <!-- RECT DATA LABELS (vertical mode) -->
917+ < template v- if = " mutableConfig.dataLabels.show && FINAL_CONFIG.orientation === 'vertical'" >
816918 < g v- for = " (dp, i) in formattedDataset" >
817919 <!-- RECT LABELS -->
818920 < text
@@ -830,7 +932,7 @@ defineExpose({
830932 < / text>
831933 < / g>
832934
833- <!-- RECT TOTAL LABEL -->
935+ <!-- RECT TOTAL LABELS -->
834936 < g v- if = " FINAL_CONFIG.style.chart.bars.totalValues.show && formattedDataset.length > 1" >
835937 < text
836938 v- for = " (total, i) in totalLabels"
@@ -846,8 +948,42 @@ defineExpose({
846948 < / g>
847949 < / template>
848950
849- <!-- Y LABELS -->
850- < template v- if = " FINAL_CONFIG.style.chart.grid.y.axisLabels.show && !FINAL_CONFIG.style.chart.bars.distributed" >
951+ <!-- RECT DATA LABELS (horizontal mode) -->
952+ < template v- if = " mutableConfig.dataLabels.show && FINAL_CONFIG.orientation === 'horizontal'" >
953+ < g v- for = " (dp, i) in formattedDataset" >
954+ <!-- RECT LABELS -->
955+ < text
956+ v- for = " (rect, j) in dp.horizontal_x"
957+ : x= " rect + ((dp.horizontal_width[j] < 0 ? 0.0001 : dp.horizontal_width[j]) / 2)"
958+ : y= " dp.horizontal_y[j] + (barSlot * (1 - FINAL_CONFIG.style.chart.bars.gapRatio / 2) / 2) + (FINAL_CONFIG.style.chart.bars.dataLabels.fontSize /3)"
959+ : font- size= " FINAL_CONFIG.style.chart.bars.dataLabels.fontSize"
960+ : fill= " FINAL_CONFIG.style.chart.bars.dataLabels.adaptColorToBackground ? adaptColorToBackground(dp.color) : FINAL_CONFIG.style.chart.bars.dataLabels.color"
961+ : font- weight= " FINAL_CONFIG.style.chart.bars.dataLabels.bold ? 'bold' : 'normal'"
962+ text- anchor= " middle"
963+ >
964+ {{ FINAL_CONFIG .style .chart .bars .showDistributedPercentage && FINAL_CONFIG .style .chart .bars .distributed ?
965+ barDataLabelPercentage (dp .proportions [j] * 100 , dp, i, j) :
966+ barDataLabel (dp .series [j], dp, i, j, dp .signedSeries [j]) }}
967+ < / text>
968+ < / g>
969+ <!-- RECT TOTAL LABELS -->
970+ < g v- if = " FINAL_CONFIG.style.chart.bars.totalValues.show && formattedDataset.length > 1" >
971+ < text
972+ v- for = " (total, i) in totalLabels"
973+ : x= " drawingArea.right + FINAL_CONFIG.style.chart.bars.totalValues.fontSize / 3"
974+ : y= " drawingArea.top + (barSlot * i) + barSlot / 2"
975+ text- anchor= " start"
976+ : font- size= " FINAL_CONFIG.style.chart.bars.totalValues.fontSize"
977+ : font- weight= " FINAL_CONFIG.style.chart.bars.totalValues.bold ? 'bold' : 'normal'"
978+ : fill= " FINAL_CONFIG.style.chart.bars.totalValues.color"
979+ >
980+ {{ barDataLabel (total .value , total, i, total .sign ) }}
981+ < / text>
982+ < / g>
983+ < / template>
984+
985+ <!-- SCALE LABELS (vertical mode) -->
986+ < template v- if = " FINAL_CONFIG.style.chart.grid.y.axisLabels.show && !FINAL_CONFIG.style.chart.bars.distributed && FINAL_CONFIG.orientation === 'vertical'" >
851987 < line
852988 v- for = " (yLabel, i) in yLabels"
853989 : x1= " drawingArea.left"
@@ -875,8 +1011,37 @@ defineExpose({
8751011 < / text>
8761012 < / template>
8771013
878- <!-- TIME LABELS -->
879- < template v- if = " FINAL_CONFIG.style.chart.grid.x.timeLabels.show" >
1014+ <!-- SCALE LABELS (horizontal mode) -->
1015+ < template v- if = " FINAL_CONFIG.style.chart.grid.y.axisLabels.show && !FINAL_CONFIG.style.chart.bars.distributed && FINAL_CONFIG.orientation === 'horizontal'" >
1016+ < line
1017+ v- for = " (yLabel, i) in yLabels"
1018+ : x1= " yLabel.horizontal_x"
1019+ : x2= " yLabel.horizontal_x"
1020+ : y1= " drawingArea.bottom"
1021+ : y2= " drawingArea.bottom + 6"
1022+ : stroke= " FINAL_CONFIG.style.chart.grid.x.axisColor"
1023+ : stroke- width= " 1"
1024+ stroke- linecap= " round"
1025+ / >
1026+ < text
1027+ v- for = " (yLabel, i) in yLabels"
1028+ : font- size= " FINAL_CONFIG.style.chart.grid.x.timeLabels.fontSize"
1029+ : font- weight= " FINAL_CONFIG.style.chart.grid.y.axisLabels.bold ? 'bold' : 'normal'"
1030+ : fill= " FINAL_CONFIG.style.chart.grid.y.axisLabels.color"
1031+ : text- anchor= " FINAL_CONFIG.style.chart.grid.x.timeLabels.rotation > 0 ? 'start' : FINAL_CONFIG.style.chart.grid.x.timeLabels.rotation < 0 ? 'end' : 'middle'"
1032+ : transform= " `translate(${yLabel.horizontal_x}, ${drawingArea.bottom + FINAL_CONFIG.style.chart.grid.x.timeLabels.fontSize * 1.3 + FINAL_CONFIG.style.chart.grid.x.timeLabels.offsetY}), rotate(${FINAL_CONFIG.style.chart.grid.x.timeLabels.rotation})`"
1033+ >
1034+ {{ dataLabel ({
1035+ p: FINAL_CONFIG .style .chart .bars .dataLabels .prefix ,
1036+ v: yLabel .value ,
1037+ s: FINAL_CONFIG .style .chart .bars .dataLabels .suffix ,
1038+ r: FINAL_CONFIG .style .chart .grid .y .axisLabels .rounding ,
1039+ }) }}
1040+ < / text>
1041+ < / template>
1042+
1043+ <!-- TIME LABELS VERTICAL -->
1044+ < template v- if = " FINAL_CONFIG.style.chart.grid.x.timeLabels.show && FINAL_CONFIG.orientation === 'vertical'" >
8801045 < text
8811046 v- for = " (timeLabel, i) in timeLabels"
8821047 : text- anchor= " FINAL_CONFIG.style.chart.grid.x.timeLabels.rotation > 0 ? 'start' : FINAL_CONFIG.style.chart.grid.x.timeLabels.rotation < 0 ? 'end' : 'middle'"
@@ -889,8 +1054,23 @@ defineExpose({
8891054 < / text>
8901055 < / template>
8911056
892- <!-- TOOLTIP TRAPS -->
893- < template v- if = " mutableConfig.showTooltip" >
1057+ <!-- TIME LABELS HORIZONTAL -->
1058+ < template v- if = " FINAL_CONFIG.style.chart.grid.x.timeLabels.show && FINAL_CONFIG.orientation === 'horizontal'" >
1059+ < text
1060+ v- for = " (timeLabel, i) in timeLabels"
1061+ text- anchor= " end"
1062+ : font- size= " FINAL_CONFIG.style.chart.grid.y.axisLabels.fontSize"
1063+ : font- weight= " FINAL_CONFIG.style.chart.grid.y.axisLabels.bold ? 'bold' : 'normal'"
1064+ : fill= " FINAL_CONFIG.style.chart.grid.y.axisLabels.color"
1065+ : x= " drawingArea.left - 8"
1066+ : y= " drawingArea.top + (barSlot * i ) + (barSlot / 2) + FINAL_CONFIG.style.chart.grid.y.axisLabels.fontSize / 3"
1067+ >
1068+ {{ timeLabel }}
1069+ < / text>
1070+ < / template>
1071+
1072+ <!-- TOOLTIP TRAPS (vertical mode) -->
1073+ < template v- if = " mutableConfig.showTooltip && FINAL_CONFIG.orientation === 'vertical'" >
8941074 < rect
8951075 v- for = " (_, i) in (slicer.end - slicer.start)"
8961076 : x= " drawingArea.left + (i * barSlot)"
@@ -904,6 +1084,21 @@ defineExpose({
9041084 / >
9051085 < / template>
9061086
1087+ <!-- TOOLTIP TRAPS (vertical mode) -->
1088+ < template v- if = " mutableConfig.showTooltip && FINAL_CONFIG.orientation === 'horizontal'" >
1089+ < rect
1090+ v- for = " (_, i) in (slicer.end - slicer.start)"
1091+ : x= " drawingArea.left"
1092+ : y= " drawingArea.top + (i * barSlot)"
1093+ : width= " drawingArea.width < 0 ? 0 : drawingArea.width"
1094+ : height= " barSlot"
1095+ @click= " selectDatapoint(i)"
1096+ @mouseenter= " useTooltip(i)"
1097+ @mouseleave= " trapIndex = null; isTooltip = false"
1098+ : fill= " i === trapIndex ? FINAL_CONFIG.style.chart.highlighter.color + opacity[FINAL_CONFIG.style.chart.highlighter.opacity] : 'transparent'"
1099+ / >
1100+ < / template>
1101+
9071102 < slot name= " svg" v- bind= " { ...drawingArea }" / >
9081103 < / svg>
9091104
0 commit comments