11<script setup>
2- import { computed , ref } from " vue" ;
2+ import { computed , ref , watch , onUnmounted , nextTick } from " vue" ;
33import { calcTooltipPosition } from " ../calcTooltipPosition" ;
44import { useMouse } from " ../useMouse" ;
5- import { opacity , setOpacity } from " ../lib" ;
5+ import { setOpacity } from " ../lib" ;
66
77const props = defineProps ({
88 backgroundColor: {
@@ -64,28 +64,82 @@ const props = defineProps({
6464 isFullscreen: {
6565 type: Boolean ,
6666 default: false
67+ },
68+ disableSmoothing: {
69+ type: Boolean ,
70+ default: false
71+ }
72+ });
73+
74+ const tooltip = ref (null );
75+
76+ const { x , y } = useMouse (props .parent );
77+ const targetPosition = ref ({ x: 0 , y: 0 });
78+ const displayPosition = ref ({ x: 0 , y: 0 });
79+
80+ const smoothing = 0.18 ;
81+ let animationFrameId = null ;
82+
83+ function animate () {
84+ if (props .disableSmoothing ) {
85+ displayPosition .value .x = targetPosition .value .x ;
86+ displayPosition .value .y = targetPosition .value .y ;
87+ return ;
88+ }
89+ displayPosition .value .x += (targetPosition .value .x - displayPosition .value .x ) * smoothing;
90+ displayPosition .value .y += (targetPosition .value .y - displayPosition .value .y ) * smoothing;
91+ animationFrameId = requestAnimationFrame (animate);
92+ }
93+
94+ watch ([x, y], ([newX , newY ]) => {
95+ targetPosition .value .x = newX;
96+ targetPosition .value .y = newY;
97+ if (props .disableSmoothing ) {
98+ displayPosition .value .x = newX;
99+ displayPosition .value .y = newY;
67100 }
68101});
69102
70- const tooltip = ref (null )
103+ watch (() => props .show , async (show ) => {
104+ if (show) {
105+ const initialX = x .value ;
106+ const initialY = y .value ;
107+ targetPosition .value .x = initialX;
108+ targetPosition .value .y = initialY;
109+ displayPosition .value .x = initialX;
110+ displayPosition .value .y = initialY;
111+ await nextTick ();
112+ if (! animationFrameId) animate ();
113+ } else {
114+ if (animationFrameId) {
115+ cancelAnimationFrame (animationFrameId);
116+ animationFrameId = null ;
117+ }
118+ }
119+ });
71120
72- const clientPosition = ref (useMouse (props .parent ));
121+ onUnmounted (() => {
122+ if (animationFrameId) cancelAnimationFrame (animationFrameId);
123+ });
73124
74125const position = computed (() => {
75- return calcTooltipPosition ({
126+ const pos = calcTooltipPosition ({
76127 tooltip: tooltip .value ,
77128 chart: props .parent ,
78- clientPosition: clientPosition .value ,
129+ clientPosition: displayPosition .value ,
79130 positionPreference: props .position ,
80131 defaultOffsetY: props .offsetY ,
81132 blockShiftY: props .blockShiftY
82133 });
83- })
134+ return {
135+ top: Math .round (pos .top ),
136+ left: Math .round (pos .left )
137+ };
138+ });
84139
85140const convertedBackground = computed (() => {
86141 return setOpacity (props .backgroundColor , props .backgroundOpacity );
87- })
88-
142+ });
89143 </script >
90144
91145<template >
@@ -98,7 +152,15 @@ const convertedBackground = computed(() => {
98152 data-cy =" tooltip"
99153 :class =" {'vue-data-ui-custom-tooltip' : isCustom, 'vue-data-ui-tooltip': !isCustom}"
100154 v-if =" show"
101- :style =" `pointer-events:none;top:${position.top}px;left:${position.left}px;${isCustom ? '' : `background:${convertedBackground};color:${color};max-width:${maxWidth};font-size:${fontSize}px`};border-radius:${borderRadius}px;border:${borderWidth}px solid ${borderColor};z-index:2147483647;`"
155+ :style =" `
156+ pointer-events:none;
157+ top:${position.top}px;
158+ left:${position.left}px;
159+ ${isCustom ? '' : `background:${convertedBackground};color:${color};max-width:${maxWidth};font-size:${fontSize}px`};
160+ border-radius:${borderRadius}px;
161+ border:${borderWidth}px solid ${borderColor};
162+ z-index:2147483647;
163+ `"
102164 >
103165 <slot name =" tooltip-before" />
104166 <slot />
@@ -120,4 +182,8 @@ const convertedBackground = computed(() => {
120182 position : fixed ;
121183 z-index : 3 ;
122184}
123- </style >
185+ .vue-data-ui-tooltip ,
186+ .vue-data-ui-custom-tooltip {
187+ will-change : top , left ;
188+ }
189+ </style >
0 commit comments