Skip to content

Commit 519d8d1

Browse files
committed
VueUiDonut added dataLabel scoped slot for custom dataLabels
1 parent eee7396 commit 519d8d1

File tree

8 files changed

+120
-53
lines changed

8 files changed

+120
-53
lines changed

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "vue-data-ui",
33
"private": false,
4-
"version": "2.0.99",
4+
"version": "2.1.0",
55
"type": "module",
66
"description": "A user-empowering data visualization Vue components library",
77
"keywords": [

src/App.vue

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2634,6 +2634,13 @@ const moodRadarConfig = ref({
26342634
const donutConfig = ref({
26352635
style: {
26362636
chart: {
2637+
layout: {
2638+
labels: {
2639+
dataLabels: {
2640+
useLabelSlots: true
2641+
}
2642+
}
2643+
},
26372644
tooltip: {
26382645
// customFormat: ({ datapoint, seriesIndex, series , config}) => {
26392646
// console.log({datapoint, seriesIndex, series, config});
@@ -4242,7 +4249,7 @@ const tableHeatmapDataset = ref([
42424249
</template>
42434250
</Box>
42444251

4245-
<Box open @copy="copyConfig(PROD_CONFIG.vue_ui_scatter)">
4252+
<Box @copy="copyConfig(PROD_CONFIG.vue_ui_scatter)">
42464253
<template #title>
42474254
<BaseIcon name="chartScatter" />
42484255
VueUiScatter
@@ -4498,7 +4505,7 @@ const tableHeatmapDataset = ref([
44984505
</template>
44994506
</Box>
45004507

4501-
<Box @copy="copyConfig(PROD_CONFIG.vue_ui_donut)">
4508+
<Box open @copy="copyConfig(PROD_CONFIG.vue_ui_donut)">
45024509
<template #title>
45034510
<BaseIcon name="chartDonut" />
45044511
VueUiDonut
@@ -4519,6 +4526,13 @@ const tableHeatmapDataset = ref([
45194526
:config="donutConfig"
45204527
@selectLegend="selectLegendDonut"
45214528
>
4529+
<template #dataLabel="{ datapoint, isBlur, isVisible, textAlign, flexAlign, percentage }">
4530+
<div v-if="isVisible" :style="`background: ${datapoint.color}30; border: 1px solid ${datapoint.color};text-align:${textAlign};display:flex; place-items:center; justify-content:flex-${flexAlign}`">
4531+
<VueUiIcon name="chartDonut" :stroke="datapoint.color"/>
4532+
{{ datapoint.name }}
4533+
</div>
4534+
</template>
4535+
45224536
<template #tooltip-before="{ seriesIndex, datapoint, series, config }">
45234537
{{ seriesIndex }}
45244538
{{ datapoint.name }}
@@ -4546,24 +4560,30 @@ const tableHeatmapDataset = ref([
45464560
</VueDataUiTest>
45474561
</template>
45484562
<template #prod>
4549-
<!-- <VueDataUi
4563+
<VueDataUi
45504564
component="VueUiDonut"
45514565
ref="donuttest"
45524566
:dataset="donutDataset"
45534567
:config="donutConfig"
45544568
@selectLegend="selectLegendDonut"
45554569
>
4570+
<template #dataLabel="{ datapoint, isBlur, isVisible, textAlign, flexAlign, percentage }">
4571+
<div v-if="isVisible" :style="`background: ${datapoint.color}30; border: 1px solid ${datapoint.color};text-align:${textAlign};display:flex; place-items:center; justify-content:flex-${flexAlign}`">
4572+
<VueUiIcon name="chartDonut" :stroke="datapoint.color"/>
4573+
{{ datapoint.name }}
4574+
</div>
4575+
</template>
45564576
<template #svg="{ svg }">
45574577
<circle :cx="svg.width / 2" :cy="svg.height / 2" :r="30" fill="#FF000033"/>
45584578
</template>
4559-
</VueDataUi> -->
4579+
</VueDataUi>
45604580
</template>
45614581
<template #config>
45624582
{{ PROD_CONFIG.vue_ui_donut }}
45634583
</template>
45644584
</Box>
45654585

4566-
<Box open @copy="copyConfig(PROD_CONFIG.vue_ui_sparkstackbar)">
4586+
<Box @copy="copyConfig(PROD_CONFIG.vue_ui_sparkstackbar)">
45674587
<template #title>
45684588
<BaseIcon name="chartSparkStackbar" />
45694589
VueUiSparkStackbar

src/components/vue-data-ui.vue

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -523,6 +523,9 @@ defineExpose({
523523
<template #svg="{ svg }">
524524
<slot name="svg" :svg="svg"></slot>
525525
</template>
526+
<template #dataLabel="{ datapoint, isBlur, isSafari, isVisible, flexAlign, textAlign, percentage }">
527+
<slot name="dataLabel" v-bind="{ datapoint, isBlur, isSafari, isVisible, flexAlign, textAlign, percentage }"/>
528+
</template>
526529
<template #legend="{ legend }">
527530
<slot name="legend" v-bind:legend="legend" />
528531
</template>

src/components/vue-ui-donut.vue

Lines changed: 82 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -397,6 +397,12 @@ function toggleFullscreen(state) {
397397
step.value += 1;
398398
}
399399
400+
const isSafari = computed(() => {
401+
return /^((?!chrome|android).)*safari/i.test(navigator.userAgent);
402+
})
403+
404+
console.log(isSafari.value)
405+
400406
function selectDatapoint(datapoint, index) {
401407
emit('selectDatapoint', { datapoint, index })
402408
}
@@ -617,46 +623,70 @@ defineExpose({
617623

618624
<!-- DATALABELS -->
619625
<g v-for="(arc, i) in currentDonut" :filter="getBlurFilter(i)">
620-
<text
621-
:data-cy="`donut-datalabel-value-${i}`"
622-
v-if="isArcBigEnough(arc) && mutableConfig.dataLabels.show"
623-
:text-anchor="calcMarkerOffsetX(arc, true).anchor"
624-
:x="calcMarkerOffsetX(arc).x"
625-
:y="calcMarkerOffsetY(arc)"
626-
:fill="arc.color"
627-
:font-size="donutConfig.style.chart.layout.labels.percentage.fontSize * 0.8"
628-
font-family="Arial"
629-
:filter="!defaultConfig.useBlurOnHover || [null, undefined].includes(selectedSerie) || selectedSerie === i ? ``: `url(#blur_${uid})`"
630-
@click="selectDatapoint(arc, i)"
631-
>
632-
633-
</text>
634-
<text
635-
:data-cy="`donut-datalabel-value-${i}`"
636-
v-if="isArcBigEnough(arc) && mutableConfig.dataLabels.show"
637-
:text-anchor="calcMarkerOffsetX(arc, true, 20).anchor"
638-
:x="calcMarkerOffsetX(arc, true, 20).x"
639-
:y="calcMarkerOffsetY(arc)"
640-
:fill="donutConfig.style.chart.layout.labels.percentage.color"
641-
:font-size="donutConfig.style.chart.layout.labels.percentage.fontSize"
642-
:style="`font-weight:${donutConfig.style.chart.layout.labels.percentage.bold ? 'bold': ''}`"
643-
@click="selectDatapoint(arc, i)"
644-
>
645-
{{ displayArcPercentage(arc, currentDonut) }} {{ donutConfig.style.chart.layout.labels.value.show ? `(${dataLabel({p: donutConfig.style.chart.layout.labels.dataLabels.prefix, v: arc.value, s: donutConfig.style.chart.layout.labels.dataLabels.suffix, rounding: donutConfig.style.chart.layout.labels.value.rounding})})` : '' }}
646-
</text>
647-
<text
648-
:data-cy="`donut-datalabel-name-${i}`"
649-
v-if="isArcBigEnough(arc, true, 20) && mutableConfig.dataLabels.show"
650-
:text-anchor="calcMarkerOffsetX(arc).anchor"
651-
:x="calcMarkerOffsetX(arc, true, 20).x"
652-
:y="calcMarkerOffsetY(arc) + donutConfig.style.chart.layout.labels.percentage.fontSize"
653-
:fill="donutConfig.style.chart.layout.labels.name.color"
654-
:font-size="donutConfig.style.chart.layout.labels.name.fontSize"
655-
:style="`font-weight:${donutConfig.style.chart.layout.labels.name.bold ? 'bold': ''}`"
656-
@click="selectDatapoint(arc, i)"
657-
>
658-
{{ arc.name }}
659-
</text>
626+
<g v-if="donutConfig.style.chart.layout.labels.dataLabels.useLabelSlots">
627+
<foreignObject
628+
:x="calcMarkerOffsetX(arc, true).anchor === 'end' ? calcMarkerOffsetX(arc).x - 120 : calcMarkerOffsetX(arc, true).anchor === 'middle' ? calcMarkerOffsetX(arc).x - 60 : calcMarkerOffsetX(arc).x"
629+
:y="calcMarkerOffsetY(arc) - (isSafari ? 20 : 0)"
630+
width="120"
631+
height="60"
632+
style="overflow: visible;"
633+
>
634+
<div :class="{'vue-ui-donut-datalabel-slot': true, 'vue-ui-donut-datalabel-slot-not-safari' : !isSafari}">
635+
<slot name="dataLabel" v-bind="{
636+
datapoint: arc,
637+
isBlur: !defaultConfig.useBlurOnHover || [null, undefined].includes(selectedSerie) || selectedSerie === i,
638+
isSafari: isSafari,
639+
isVisible: isArcBigEnough(arc) && mutableConfig.dataLabels.show,
640+
textAlign: calcMarkerOffsetX(arc, true, 16, true).anchor,
641+
flexAlign: calcMarkerOffsetX(arc, true, 16).anchor,
642+
percentage: displayArcPercentage(arc, currentDonut),
643+
}"/>
644+
</div>
645+
</foreignObject>
646+
</g>
647+
648+
<g v-else>
649+
<text
650+
:data-cy="`donut-datalabel-value-${i}`"
651+
v-if="isArcBigEnough(arc) && mutableConfig.dataLabels.show"
652+
:text-anchor="calcMarkerOffsetX(arc, true).anchor"
653+
:x="calcMarkerOffsetX(arc).x"
654+
:y="calcMarkerOffsetY(arc)"
655+
:fill="arc.color"
656+
:font-size="donutConfig.style.chart.layout.labels.percentage.fontSize * 0.8"
657+
font-family="Arial"
658+
:filter="!defaultConfig.useBlurOnHover || [null, undefined].includes(selectedSerie) || selectedSerie === i ? ``: `url(#blur_${uid})`"
659+
@click="selectDatapoint(arc, i)"
660+
>
661+
662+
</text>
663+
<text
664+
:data-cy="`donut-datalabel-value-${i}`"
665+
v-if="isArcBigEnough(arc) && mutableConfig.dataLabels.show"
666+
:text-anchor="calcMarkerOffsetX(arc, true, 20).anchor"
667+
:x="calcMarkerOffsetX(arc, true, 20).x"
668+
:y="calcMarkerOffsetY(arc)"
669+
:fill="donutConfig.style.chart.layout.labels.percentage.color"
670+
:font-size="donutConfig.style.chart.layout.labels.percentage.fontSize"
671+
:style="`font-weight:${donutConfig.style.chart.layout.labels.percentage.bold ? 'bold': ''}`"
672+
@click="selectDatapoint(arc, i)"
673+
>
674+
{{ displayArcPercentage(arc, currentDonut) }} {{ donutConfig.style.chart.layout.labels.value.show ? `(${dataLabel({p: donutConfig.style.chart.layout.labels.dataLabels.prefix, v: arc.value, s: donutConfig.style.chart.layout.labels.dataLabels.suffix, rounding: donutConfig.style.chart.layout.labels.value.rounding})})` : '' }}
675+
</text>
676+
<text
677+
:data-cy="`donut-datalabel-name-${i}`"
678+
v-if="isArcBigEnough(arc, true, 20) && mutableConfig.dataLabels.show"
679+
:text-anchor="calcMarkerOffsetX(arc).anchor"
680+
:x="calcMarkerOffsetX(arc, true, 20).x"
681+
:y="calcMarkerOffsetY(arc) + donutConfig.style.chart.layout.labels.percentage.fontSize"
682+
:fill="donutConfig.style.chart.layout.labels.name.color"
683+
:font-size="donutConfig.style.chart.layout.labels.name.fontSize"
684+
:style="`font-weight:${donutConfig.style.chart.layout.labels.name.bold ? 'bold': ''}`"
685+
@click="selectDatapoint(arc, i)"
686+
>
687+
{{ arc.name }}
688+
</text>
689+
</g>
660690
</g>
661691

662692
<!-- LEGEND AS G -->
@@ -801,4 +831,16 @@ path {
801831
width:100%;
802832
}
803833
834+
.vue-ui-donut-datalabel-slot {
835+
width: 100%;
836+
height: -webkit-fit-content;
837+
height: fit-content;
838+
}
839+
840+
.vue-ui-donut-datalabel-slot-not-safari {
841+
position: absolute;
842+
top:0;
843+
transform: translateY(-50%);
844+
}
845+
804846
</style>

src/default_configs.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -351,6 +351,7 @@
351351
"labels": {
352352
"dataLabels": {
353353
"show": true,
354+
"useLabelSlots": false,
354355
"hideUnderValue": 3,
355356
"prefix": "",
356357
"suffix": ""

src/lib.js

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -622,19 +622,19 @@ export function createUid() {
622622
});
623623
}
624624

625-
export function calcMarkerOffsetX(arc, isTitle = false, offset = 16) {
625+
export function calcMarkerOffsetX(arc, isTitle = false, offset = 16, useCss = false) {
626626
let x = 0;
627627
let offsetX = isTitle ? offset : 0;
628-
let anchor = "middle";
628+
let anchor = useCss ? 'center' : "middle";
629629
if (arc.center.endX > arc.cx) {
630630
x = arc.center.endX + offset + offsetX;
631-
anchor = "start";
631+
anchor = useCss ? 'left' : "start";
632632
} else if (arc.center.endX < arc.cx) {
633633
x = arc.center.endX - offset - offsetX;
634-
anchor = "end";
634+
anchor = useCss ? 'right' : "end";
635635
} else {
636636
x = arc.centerX + offsetX;
637-
anchor = "middle";
637+
anchor = useCss ? 'center' : "middle";
638638
}
639639
return { x, anchor }
640640
}

types/vue-data-ui.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2534,6 +2534,7 @@ declare module 'vue-data-ui' {
25342534
labels?: {
25352535
dataLabels?: {
25362536
show?: boolean;
2537+
useLabelSlots?: boolean;
25372538
hideUnderValue?: number;
25382539
prefix?: string;
25392540
suffix?: string;

0 commit comments

Comments
 (0)