Skip to content

Commit 30b4964

Browse files
committed
Types - Added tooltip types to VueUiWordCloudConfig
1 parent 19295a0 commit 30b4964

File tree

2 files changed

+104
-6
lines changed

2 files changed

+104
-6
lines changed

src/components/vue-ui-word-cloud.vue

Lines changed: 88 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { ref, watch, computed, nextTick, onMounted, onBeforeUnmount } from 'vue'
33
import themes from "../themes.json";
44
import Title from '../atoms/Title.vue';
55
import UserOptions from '../atoms/UserOptions.vue';
6-
import { checkNaN, createUid, createWordCloudDatasetFromPlainText } from '../lib';
6+
import { checkNaN, createUid, createWordCloudDatasetFromPlainText, isFunction } from '../lib';
77
import { debounce } from '../canvas-lib';
88
import {
99
createCsvContent,
@@ -25,6 +25,7 @@ import { usePrinter } from '../usePrinter';
2525
import { useResponsive } from '../useResponsive';
2626
import { useConfig } from '../useConfig';
2727
import PackageVersion from '../atoms/PackageVersion.vue';
28+
import Tooltip from '../atoms/Tooltip.vue';
2829
2930
const { vue_ui_word_cloud: DEFAULT_CONFIG } = useConfig();
3031
@@ -65,6 +66,7 @@ const wordCloudChart = ref(null);
6566
const chartTitle = ref(null);
6667
const titleStep = ref(0);
6768
const tableStep = ref(0);
69+
const isTooltip = ref(false);
6870
6971
const FINAL_CONFIG = computed({
7072
get: () => {
@@ -181,6 +183,7 @@ const { isPrinting, isImaging, generatePdf, generateImage } = usePrinter({
181183
182184
const mutableConfig = ref({
183185
showTable: FINAL_CONFIG.value.table.show,
186+
showTooltip: FINAL_CONFIG.value.style.chart.tooltip.show,
184187
});
185188
186189
function measureTextSize(text, fontSize, fontFamily = "Arial") {
@@ -347,14 +350,56 @@ function toggleTable() {
347350
mutableConfig.value.showTable = !mutableConfig.value.showTable;
348351
}
349352
353+
function toggleTooltip() {
354+
mutableConfig.value.showTooltip = !mutableConfig.value.showTooltip;
355+
}
356+
350357
defineExpose({
351358
getData,
352359
generateCsv,
353360
generatePdf,
354361
generateImage,
355-
toggleTable
362+
toggleTable,
363+
toggleTooltip
356364
});
357365
366+
const selectedWord = ref(null);
367+
const useCustomFormat = ref(false);
368+
const tooltipContent = ref('');
369+
const dataTooltipSlot = ref(null);
370+
371+
function useTooltip(word) {
372+
if (!mutableConfig.value.showTooltip) return;
373+
selectedWord.value = word.id;
374+
dataTooltipSlot.value = { datapoint: word, config: FINAL_CONFIG.value };
375+
const customFormat = FINAL_CONFIG.value.style.chart.tooltip.customFormat;
376+
useCustomFormat.value = false;
377+
378+
if (isFunction(customFormat)) {
379+
try {
380+
const customFormatString = customFormat({
381+
datapoint: word,
382+
config: FINAL_CONFIG.value
383+
});
384+
if (typeof customFormatString === 'string') {
385+
tooltipContent.value = customFormatString;
386+
useCustomFormat.value = true;
387+
}
388+
} catch (err) {
389+
console.warn('Custom format cannot be applied.');
390+
useCustomFormat.value = false;
391+
}
392+
}
393+
394+
if (!useCustomFormat.value) {
395+
let html = `<svg viewBox="0 0 10 10" height="${FINAL_CONFIG.value.style.chart.tooltip.fontSize}"><circle cx="5" cy="5" r="5" fill="${word.color}"/></svg><span>${word.name}:</span><b>${(word.value || 0).toFixed(FINAL_CONFIG.value.style.chart.tooltip.roundingValue)}</b>`;
396+
397+
tooltipContent.value = `<div dir="auto" style="display:flex; gap:4px; align-items:center; jsutify-content:center;">${html}</div>`;
398+
}
399+
400+
isTooltip.value = true;
401+
}
402+
358403
</script>
359404

360405
<template>
@@ -392,11 +437,14 @@ defineExpose({
392437
:titles="{ ...FINAL_CONFIG.userOptions.buttonTitles }"
393438
:chartElement="wordCloudChart"
394439
:position="FINAL_CONFIG.userOptions.position"
440+
:hasTooltip="FINAL_CONFIG.style.chart.tooltip.show && FINAL_CONFIG.userOptions.buttons.tooltip"
441+
:isTooltip="mutableConfig.showTooltip"
395442
@toggleFullscreen="toggleFullscreen"
396443
@generatePdf="generatePdf"
397444
@generateCsv="generateCsv"
398445
@generateImage="generateImage"
399-
@toggleTable="toggleTable"
446+
@toggleTable="toggleTable"
447+
@toggleTooltip="toggleTooltip"
400448
>
401449
<template #optionPdf v-if="$slots.optionPdf">
402450
<slot name="optionPdf" />
@@ -429,10 +477,12 @@ defineExpose({
429477
:font-weight="FINAL_CONFIG.style.chart.words.bold ? 'bold' : 'normal'" :key="index"
430478
:x="word.x" :y="word.y" :font-size="word.fontSize"
431479
:transform="`translate(${word.width / 2}, ${word.height / 2})`"
432-
:style="`animation-delay:${index * FINAL_CONFIG.animationDelayMs}ms !important`"
433-
:class="{'animated': FINAL_CONFIG.useCssAnimation}"
480+
:class="{'animated': FINAL_CONFIG.useCssAnimation, 'word-selected': selectedWord && selectedWord === word.id && mutableConfig.showTooltip, 'word-not-selected': selectedWord && selectedWord !== word.id && mutableConfig.showTooltip }"
434481
text-anchor="middle"
435482
dominant-baseline="middle"
483+
@mouseover="useTooltip(word)"
484+
@mouseleave="selectedWord = null; isTooltip = false"
485+
:style="`animation-delay:${index * FINAL_CONFIG.animationDelayMs}ms !important;`"
436486
>
437487
{{ word.name }}
438488
</text>
@@ -445,6 +495,29 @@ defineExpose({
445495
<slot name="watermark" v-bind="{ isPrinting: isPrinting || isImaging }"/>
446496
</div>
447497

498+
<Tooltip
499+
:show="mutableConfig.showTooltip && isTooltip"
500+
:backgroundColor="FINAL_CONFIG.style.chart.tooltip.backgroundColor"
501+
:color="FINAL_CONFIG.style.chart.tooltip.color"
502+
:fontSize="FINAL_CONFIG.style.chart.tooltip.fontSize"
503+
:borderRadius="FINAL_CONFIG.style.chart.tooltip.borderRadius"
504+
:borderColor="FINAL_CONFIG.style.chart.tooltip.borderColor"
505+
:borderWidth="FINAL_CONFIG.style.chart.tooltip.borderWidth"
506+
:backgroundOpacity="FINAL_CONFIG.style.chart.tooltip.backgroundOpacity"
507+
:position="FINAL_CONFIG.style.chart.tooltip.position"
508+
:offsetY="FINAL_CONFIG.style.chart.tooltip.offsetY"
509+
:parent="wordCloudChart"
510+
:content="tooltipContent"
511+
:isCustom="useCustomFormat"
512+
>
513+
<template #tooltip-before>
514+
<slot name="tooltip-before" v-bind="{...dataTooltipSlot}"></slot>
515+
</template>
516+
<template #tooltip-after>
517+
<slot name="tooltip-after" v-bind="{...dataTooltipSlot}"></slot>
518+
</template>
519+
</Tooltip>
520+
448521
<div ref="chartSlicer" :style="`width:100%;background:transparent`" data-html2canvas-ignore>
449522
<MonoSlicer
450523
v-if="FINAL_CONFIG.style.chart.zoom.show"
@@ -513,7 +586,7 @@ defineExpose({
513586
text.animated {
514587
opacity:0;
515588
user-select: none;
516-
animation: word-opacity 0.3s ease-in forwards;
589+
animation: word-opacity 0.2s ease-in forwards;
517590
transform-origin: center;
518591
}
519592
@@ -525,4 +598,13 @@ text.animated {
525598
opacity: 1;
526599
}
527600
}
601+
602+
.animated.word-selected {
603+
opacity: 1;
604+
}
605+
.word-not-selected {
606+
opacity: 0.5 !important;
607+
}
608+
609+
528610
</style>

types/vue-data-ui.d.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4775,6 +4775,18 @@ declare module 'vue-data-ui' {
47754775
value: number;
47764776
}
47774777

4778+
export type VueUiWordCloudDatapoint = {
4779+
color: string;
4780+
fontSize: number;
4781+
height: number;
4782+
id: string;
4783+
name: string;
4784+
value: number;
4785+
width: number;
4786+
x: number;
4787+
y: number;
4788+
}
4789+
47784790
export type VueUiWordCloudConfig = {
47794791
responsive?: boolean;
47804792
theme?: string;
@@ -4800,6 +4812,10 @@ declare module 'vue-data-ui' {
48004812
usePalette?: boolean;
48014813
};
48024814
title?: ChartTitle;
4815+
tooltip?: ChartTooltip & {
4816+
roundingValue?: number;
4817+
customFormat?: null | ((params: VueUiTooltipParams<VueUiWordCloudDatapoint, VueUiDonutConfig>) => string);
4818+
};
48034819
}
48044820
},
48054821
table?: {

0 commit comments

Comments
 (0)