@@ -225,43 +225,129 @@ const mutableSvg = ref({
225225
226226const selectedSide = ref (null );
227227
228+ const selectedSideLabelCoordinates = computed (() => {
229+ switch (selectedSide .value ) {
230+ case ' TL' :
231+ return {
232+ x: mutableSvg .value .startX + mutableSvg .value .width / 2 ,
233+ y: mutableSvg .value .height ,
234+ text: quadrantConfig .value .style .chart .layout .labels .quadrantLabels .tl .text || ' Top Left' ,
235+ fontSize: quadrantConfig .value .style .chart .layout .labels .quadrantLabels .tl .fontSize ,
236+ fill: quadrantConfig .value .style .chart .layout .labels .quadrantLabels .tl .color ,
237+ bold: quadrantConfig .value .style .chart .layout .labels .quadrantLabels .tl .bold
238+ }
239+ case ' TR' :
240+ return {
241+ x: mutableSvg .value .startX + mutableSvg .value .width / 2 ,
242+ y: mutableSvg .value .height ,
243+ text: quadrantConfig .value .style .chart .layout .labels .quadrantLabels .tr .text || ' Top Right' ,
244+ fontSize: quadrantConfig .value .style .chart .layout .labels .quadrantLabels .tr .fontSize ,
245+ fill: quadrantConfig .value .style .chart .layout .labels .quadrantLabels .tr .color ,
246+ bold: quadrantConfig .value .style .chart .layout .labels .quadrantLabels .tr .bold
247+ }
248+ case ' BR' :
249+ return {
250+ x: mutableSvg .value .startX + mutableSvg .value .width / 2 ,
251+ y: mutableSvg .value .height * 1.678 ,
252+ text: quadrantConfig .value .style .chart .layout .labels .quadrantLabels .br .text || ' Bottom Right' ,
253+ fontSize: quadrantConfig .value .style .chart .layout .labels .quadrantLabels .br .fontSize ,
254+ fill: quadrantConfig .value .style .chart .layout .labels .quadrantLabels .br .color ,
255+ bold: quadrantConfig .value .style .chart .layout .labels .quadrantLabels .br .bold
256+ }
257+ case ' BL' :
258+ return {
259+ x: mutableSvg .value .startX + mutableSvg .value .width / 2 ,
260+ y: mutableSvg .value .height * 1.678 ,
261+ text: quadrantConfig .value .style .chart .layout .labels .quadrantLabels .bl .text || ' Bottom Left' ,
262+ fontSize: quadrantConfig .value .style .chart .layout .labels .quadrantLabels .bl .fontSize ,
263+ fill: quadrantConfig .value .style .chart .layout .labels .quadrantLabels .bl .color ,
264+ bold: quadrantConfig .value .style .chart .layout .labels .quadrantLabels .bl .bold
265+ }
266+
267+ default :
268+ return {x: 0 , y: 0 , text: ' ' , fontSize: 0 , fill: ' none' , bold: false }
269+ }
270+ })
271+
272+ const currentAnimationFrame = ref (null );
273+ const isAnimating = ref (false );
274+
275+ function zoomOnSide ({ targetX, targetY, targetW, targetH}) {
276+ const differentials = {
277+ x: targetX - mutableSvg .value .startX ,
278+ y: targetY - mutableSvg .value .startY ,
279+ w: targetW - mutableSvg .value .width ,
280+ h: targetH - mutableSvg .value .height
281+ }
282+
283+ const steps = quadrantConfig .value .zoomAnimationFrames ;
284+ let init = 0 ;
285+ function anim () {
286+ isAnimating .value = true ;
287+ mutableSvg .value .startX += (differentials .x / steps);
288+ mutableSvg .value .startY += (differentials .y / steps);
289+ mutableSvg .value .width += (differentials .w / steps);
290+ mutableSvg .value .height += (differentials .h / steps);
291+ init += 1 ;
292+ if (init < steps) {
293+ currentAnimationFrame .value = requestAnimationFrame (anim)
294+ } else {
295+ isAnimating .value = false ;
296+ }
297+ }
298+ anim ()
299+ }
300+
228301function selectQuadrantSide (side ) {
302+ if (isAnimating .value ) {
303+ return ;
304+ }
229305 if (isZoom .value && selectedSide .value === side) {
230- mutableSvg .value .startX = 0 ;
231- mutableSvg .value .startY = 0 ;
232- mutableSvg .value .width = svg .value .width ;
233- mutableSvg .value .height = svg .value .height ;
306+ zoomOnSide ({
307+ targetX: 0 ,
308+ targetY: 0 ,
309+ targetW: svg .value .width ,
310+ targetH: svg .value .height
311+ })
234312 selectedSide .value = null ;
235313 isZoom .value = false ;
236314 } else {
237315 selectedSide .value = side;
238316 switch (side) {
239317 case ' TL' :
240- mutableSvg .value .startX = 0 ;
241- mutableSvg .value .startY = 0 ;
242- mutableSvg .value .width = svg .value .width / 2 + svg .value .left ;
243- mutableSvg .value .height = svg .value .height / 2 + svg .value .top ;
318+ zoomOnSide ({
319+ targetX: 0 ,
320+ targetY: 0 ,
321+ targetW: svg .value .width / 2 + svg .value .left ,
322+ targetH: svg .value .height / 2 + svg .value .top
323+ })
244324 break ;
245325
246326 case ' TR' :
247- mutableSvg .value .startX = svg .value .width / 2 - svg .value .left ;
248- mutableSvg .value .startY = 0 ;
249- mutableSvg .value .width = svg .value .width / 2 + svg .value .left ;
250- mutableSvg .value .height = svg .value .height / 2 + svg .value .top ;
327+ zoomOnSide ({
328+ targetX: svg .value .width / 2 - svg .value .left ,
329+ targetY: 0 ,
330+ targetW: svg .value .width / 2 + svg .value .left ,
331+ targetH: svg .value .height / 2 + svg .value .top
332+ })
251333 break ;
252334
253335 case ' BR' :
254- mutableSvg .value .startX = svg .value .width / 2 - svg .value .left ;
255- mutableSvg .value .startY = svg .value .height / 2 - svg .value .top ;
256- mutableSvg .value .width = svg .value .width / 2 + svg .value .left ;
257- mutableSvg .value .height = svg .value .height / 2 + svg .value .top ;
336+ zoomOnSide ({
337+ targetX: svg .value .width / 2 - svg .value .left ,
338+ targetY: svg .value .height / 2 - svg .value .top ,
339+ targetW: svg .value .width / 2 + svg .value .left ,
340+ targetH: svg .value .height / 2 + svg .value .top
341+ })
258342 break ;
259343
260344 case ' BL' :
261- mutableSvg .value .startX = 0 ;
262- mutableSvg .value .startY = svg .value .height / 2 - svg .value .top ;
263- mutableSvg .value .width = svg .value .width / 2 + svg .value .left ;
264- mutableSvg .value .height = svg .value .height / 2 + svg .value .top ;
345+ zoomOnSide ({
346+ targetX: 0 ,
347+ targetY: svg .value .height / 2 - svg .value .top ,
348+ targetW: svg .value .width / 2 + svg .value .left ,
349+ targetH: svg .value .height / 2 + svg .value .top
350+ })
265351 break ;
266352
267353 default :
@@ -1205,6 +1291,19 @@ defineExpose({
12051291 />
12061292 </g >
12071293
1294+ <g v-if =" selectedSide && !isAnimating" >
1295+ <text
1296+ :x =" selectedSideLabelCoordinates.x"
1297+ :y =" selectedSideLabelCoordinates.y - (selectedSideLabelCoordinates.fontSize / 1.5)"
1298+ :font-size =" selectedSideLabelCoordinates.fontSize / 1.5"
1299+ :fill =" selectedSideLabelCoordinates.fill"
1300+ text-anchor =" middle"
1301+ :font-weight =" selectedSideLabelCoordinates.bold ? 'bold' : 'normal'"
1302+ >
1303+ {{ selectedSideLabelCoordinates.text }}
1304+ </text >
1305+ </g >
1306+
12081307 <!-- LEGEND AS G -->
12091308 <foreignObject
12101309 v-if =" quadrantConfig.style.chart.legend.show && mutableConfig.inside && !isPrinting"
@@ -1284,7 +1383,6 @@ defineExpose({
12841383 </g >
12851384 <slot name =" svg" :svg =" svg" />
12861385 </svg >
1287- {{ selectedSide }}
12881386
12891387 <Skeleton
12901388 v-if =" !isDataset"
0 commit comments