11import { DisplayObject } from '@antv/g' ;
22import { deepMix } from '@antv/util' ;
33import { group } from '@antv/vendor/d3-array' ;
4+ import { isPolar } from '../utils/coordinate' ;
45import {
56 createDatumof ,
67 createUseState ,
@@ -21,7 +22,6 @@ export function elementHoverScale(
2122 datum,
2223 groupKey = ( element ) => element ,
2324 scaleFactor = 1.04 ,
24- scaleOrigin = 'center center' ,
2525 shadow = true ,
2626 shadowColor = 'rgba(0, 0, 0, 0.4)' ,
2727 shadowBlur = 10 ,
@@ -31,6 +31,7 @@ export function elementHoverScale(
3131 delay = 60 ,
3232 emitter,
3333 state = { } ,
34+ coordinate,
3435 } : Record < string , any > ,
3536) {
3637 // Helper function to get current valid elements
@@ -49,17 +50,19 @@ export function elementHoverScale(
4950 const { updateState, removeState, hasState } = useState ( valueof ) ;
5051
5152 const originalStyles = new Map < DisplayObject , Record < string , any > > ( ) ;
52- const hoveredElements = new Set < DisplayObject > ( ) ;
5353
5454 let out ;
5555
5656 const applyHoverEffect = ( element : DisplayObject ) => {
57- if ( hoveredElements . has ( element ) ) return ;
57+ if ( originalStyles . has ( element ) ) return ;
5858
59- // Capture current state before applying effect
6059 const currentTransform = element . style . transform || '' ;
6160 const currentTransformOrigin = element . style . transformOrigin || '' ;
61+ // Normalize 'none' to empty string as 'none' is not a valid transform value for concatenation
62+ const normalizedTransform =
63+ currentTransform === 'none' ? '' : currentTransform ;
6264
65+ // Save original styles for restoration
6366 originalStyles . set ( element , {
6467 transform : currentTransform ,
6568 transformOrigin : currentTransformOrigin ,
@@ -70,26 +73,21 @@ export function elementHoverScale(
7073 shadowOffsetY : element . style . shadowOffsetY || 0 ,
7174 } ) ;
7275
73- // Treat 'none' as empty string since it means no transform
74- const prefix =
75- currentTransform && currentTransform !== 'none' ? currentTransform : '' ;
76- const scaleTransform = `scale(${ scaleFactor } )` ;
77-
78- // Build new transform: append or replace scale in existing transform
79- let newTransform : string ;
80- if ( prefix && ! prefix . includes ( 'scale' ) ) {
81- newTransform = `${ prefix } ${ scaleTransform } ` . trimStart ( ) ;
82- } else if ( prefix && prefix . includes ( 'scale' ) ) {
83- newTransform = prefix
84- . replace ( / s c a l e \( [ ^ ) ] + \) / g, scaleTransform )
85- . trimStart ( ) ;
86- } else {
87- newTransform = scaleTransform ;
76+ // For polar coordinates without transform, set transformOrigin to coordinate center
77+ // When legend filtering occurs, element positioning changes from translate to absolute path coords
78+ // Setting transformOrigin to center ensures consistent radial growth in both cases
79+ if ( coordinate && isPolar ( coordinate ) && ! normalizedTransform ) {
80+ const center = coordinate . getCenter ( ) as [ number , number ] ;
81+ element . style . transformOrigin = `${ center [ 0 ] } px ${ center [ 1 ] } px` ;
8882 }
8983
90- // Apply styles
91- element . style . transformOrigin = scaleOrigin ;
92- element . style . transform = newTransform ;
84+ // Apply scale transform
85+ const scaleTransform = `scale(${ scaleFactor } )` ;
86+ element . style . transform = normalizedTransform
87+ ? `${ normalizedTransform } ${ scaleTransform } `
88+ : scaleTransform ;
89+
90+ // Apply visual effects
9391 element . style . zIndex = zIndex ;
9492
9593 if ( shadow ) {
@@ -98,8 +96,6 @@ export function elementHoverScale(
9896 element . style . shadowOffsetX = shadowOffsetX ;
9997 element . style . shadowOffsetY = shadowOffsetY ;
10098 }
101-
102- hoveredElements . add ( element ) ;
10399 } ;
104100
105101 const removeHoverEffect = ( element : DisplayObject ) => {
@@ -115,7 +111,6 @@ export function elementHoverScale(
115111 element . style . shadowOffsetX = original . shadowOffsetX ;
116112 element . style . shadowOffsetY = original . shadowOffsetY ;
117113
118- hoveredElements . delete ( element ) ;
119114 originalStyles . delete ( element ) ;
120115 } ;
121116
@@ -131,25 +126,25 @@ export function elementHoverScale(
131126 if ( out ) clearTimeout ( out ) ;
132127
133128 const currentKeyGroup = group ( validElements , groupKey ) ;
134- const k = groupKey ( element ) ;
135- const currentGroup = currentKeyGroup . get ( k ) ;
129+ const currentKey = groupKey ( element ) ;
130+ const currentGroup = currentKeyGroup . get ( currentKey ) ;
136131
137132 if ( ! currentGroup ) return ;
138133
139134 const groupSet = new Set ( currentGroup ) ;
140135
141136 // Remove hover effects from elements not in current group
142- for ( const e of validElements ) {
143- if ( ! groupSet . has ( e ) ) {
144- removeState ( e , 'active' ) ;
145- removeHoverEffect ( e ) ;
137+ for ( const element of validElements ) {
138+ if ( ! groupSet . has ( element ) ) {
139+ removeState ( element , 'active' ) ;
140+ removeHoverEffect ( element ) ;
146141 }
147142 }
148143
149144 // Apply hover effects to current group
150- for ( const e of currentGroup ) {
151- if ( ! hasState ( e , 'active' ) ) updateState ( e , 'active' ) ;
152- applyHoverEffect ( e as DisplayObject ) ;
145+ for ( const element of currentGroup ) {
146+ if ( ! hasState ( element , 'active' ) ) updateState ( element , 'active' ) ;
147+ applyHoverEffect ( element as DisplayObject ) ;
153148 }
154149
155150 // Emit events
@@ -175,21 +170,18 @@ export function elementHoverScale(
175170 const validElements = getCurrentElements ( ) ;
176171
177172 // Remove hover effects and states from all valid elements
178- for ( const e of validElements ) {
179- removeState ( e , 'active' ) ;
180- removeHoverEffect ( e ) ;
173+ for ( const element of validElements ) {
174+ removeState ( element , 'active' ) ;
175+ removeHoverEffect ( element ) ;
181176 }
182177
183- hoveredElements . clear ( ) ;
184-
185178 if ( nativeEvent ) {
186179 emitter . emit ( 'element:unhoverscale' , { nativeEvent } ) ;
187180 }
188181 } ;
189182
190- const pointerout = ( event ) => {
191- if ( delay > 0 ) delayReset ( ) ;
192- else reset ( ) ;
183+ const pointerout = ( ) => {
184+ delay > 0 ? delayReset ( ) : reset ( ) ;
193185 } ;
194186
195187 const pointerleave = ( ) => {
@@ -232,19 +224,17 @@ export function elementHoverScale(
232224
233225 // Clean up all hover effects from current elements
234226 const validElements = getCurrentElements ( ) ;
235- for ( const e of validElements ) {
236- removeHoverEffect ( e ) ;
227+ for ( const element of validElements ) {
228+ removeHoverEffect ( element ) ;
237229 }
238230 originalStyles . clear ( ) ;
239- hoveredElements . clear ( ) ;
240231 } ;
241232}
242233
243234export function ElementHoverScale ( {
244235 delay,
245236 createGroup,
246237 scale : scaleFactorParam ,
247- scaleOrigin,
248238 shadow,
249239 shadowColor,
250240 shadowBlur,
@@ -257,6 +247,7 @@ export function ElementHoverScale({
257247 const { container, view, options } = context ;
258248 const plotArea = selectPlotArea ( container ) ;
259249 const datumof = createDatumof ( view ) ;
250+ const { coordinate } = view ;
260251
261252 return elementHoverScale ( plotArea , {
262253 elements : selectG2Elements ,
@@ -266,7 +257,6 @@ export function ElementHoverScale({
266257 : undefined ,
267258 state : mergeState ( options , [ 'active' ] ) ,
268259 scaleFactor : scaleFactorParam ,
269- scaleOrigin,
270260 shadow,
271261 shadowColor,
272262 shadowBlur,
@@ -275,6 +265,7 @@ export function ElementHoverScale({
275265 zIndex,
276266 delay,
277267 emitter,
268+ coordinate,
278269 ...rest ,
279270 } ) ;
280271 } ;
0 commit comments