88 RectStyleProps ,
99 TextStyleProps ,
1010} from '@antv/g' ;
11+ import { isUndefined } from '@antv/util' ;
1112import { Marker } from '../../marker' ;
1213import type { ComponentOptions } from '../../../core' ;
1314import { Component } from '../../../core' ;
@@ -50,6 +51,8 @@ export type CategoryItemStyleProps = GroupStyleProps &
5051 x ?: number ;
5152 y ?: number ;
5253 poptip ?: PoptipStyleProps & PoptipRender ;
54+ focus ?: boolean ;
55+ focusMarkerSize ?: number ;
5356 } ;
5457
5558export type CategoryItemOptions = ComponentOptions < CategoryItemStyleProps > ;
@@ -62,6 +65,8 @@ const CLASS_NAMES = classNames(
6265 labelGroup : 'label-group' ,
6366 label : 'label' ,
6467 valueGroup : 'value-group' ,
68+ focusGroup : 'focus-group' ,
69+ focus : 'focus' ,
6570 value : 'value' ,
6671 backgroundGroup : 'background-group' ,
6772 background : 'background' ,
@@ -111,6 +116,8 @@ export class CategoryItem extends Component<CategoryItemStyleProps> {
111116
112117 private poptipGroup ! : Poptip ;
113118
119+ private focusGroup ! : Selection < Group > ;
120+
114121 private markerGroup ! : Selection < Group > ;
115122
116123 private labelGroup ! : Selection < Group > ;
@@ -130,13 +137,17 @@ export class CategoryItem extends Component<CategoryItemStyleProps> {
130137 private get actualSpace ( ) {
131138 const label = this . labelGroup ;
132139 const value = this . valueGroup ;
133- const { markerSize } = this . attributes ;
140+ const { markerSize, focus , focusMarkerSize } = this . attributes ;
134141 const { width : labelWidth , height : labelHeight } = label . node ( ) . getBBox ( ) ;
135142 const { width : valueWidth , height : valueHeight } = value . node ( ) . getBBox ( ) ;
143+
144+ const focusWidth = focus ? focusMarkerSize ?? 12 : 0 ;
145+
136146 return {
137147 markerWidth : markerSize ,
138148 labelWidth,
139149 valueWidth,
150+ focusWidth,
140151 height : Math . max ( markerSize , labelHeight , valueHeight ) ,
141152 } ;
142153 }
@@ -150,41 +161,50 @@ export class CategoryItem extends Component<CategoryItemStyleProps> {
150161 return [ span1 / basis , span2 / basis ] ;
151162 }
152163
164+ setAttribute ( n : any , v : any ) {
165+ super . setAttribute ( n , v ) ;
166+ }
167+
153168 private get shape ( ) {
154169 const { markerSize, width : fullWidth } = this . attributes ;
155170 const actualSpace = this . actualSpace ;
156- const { markerWidth, height } = actualSpace ;
171+ const { markerWidth, focusWidth , height } = actualSpace ;
157172 let { labelWidth, valueWidth } = this . actualSpace ;
158- const [ spacing1 , spacing2 ] = this . spacing ;
173+ const [ spacing1 , spacing2 , spacing3 ] = this . spacing ;
159174
160175 if ( fullWidth ) {
161- const width = fullWidth - markerSize - spacing1 - spacing2 ;
176+ const width = fullWidth - markerSize - spacing1 - spacing2 - focusWidth - spacing3 ;
162177 const [ span1 , span2 ] = this . span ;
163178 [ labelWidth , valueWidth ] = [ span1 * width , span2 * width ] ;
164179 }
165180
166- const width = markerWidth + labelWidth + valueWidth + spacing1 + spacing2 ;
167- return { width, height, markerWidth, labelWidth, valueWidth } ;
181+ const width = markerWidth + labelWidth + valueWidth + spacing1 + spacing2 + focusWidth + spacing3 ;
182+ return { width, height, markerWidth, labelWidth, valueWidth, focusWidth } ;
168183 }
169184
170185 private get spacing ( ) {
171- const { spacing } = this . attributes ;
172- if ( ! spacing ) return [ 0 , 0 ] ;
173- const [ spacing1 , spacing2 ] = parseSeriesAttr ( spacing ) ;
174- if ( this . showValue ) return [ spacing1 , spacing2 ] ;
175- return [ spacing1 , 0 ] ;
186+ const { spacing, focus } = this . attributes ;
187+ if ( ! spacing ) return [ 0 , 0 , 0 ] ;
188+ const [ spacing1 , spacing2 , spacing3 ] = parseSeriesAttr ( spacing ) ;
189+ return [ spacing1 , this . showValue ? spacing2 : 0 , focus ? spacing3 : 0 ] ;
176190 }
177191
178192 private get layout ( ) {
179- const { markerWidth, labelWidth, valueWidth, width, height } = this . shape ;
180- const [ spacing1 , spacing2 ] = this . spacing ;
193+ const { markerWidth, labelWidth, valueWidth, focusWidth , width, height } = this . shape ;
194+ const [ spacing1 , spacing2 , spacing3 ] = this . spacing ;
181195 return {
182196 height,
183197 width,
184198 markerWidth,
185199 labelWidth,
186200 valueWidth,
187- position : [ markerWidth / 2 , markerWidth + spacing1 , markerWidth + labelWidth + spacing1 + spacing2 ] ,
201+ focusWidth,
202+ position : [
203+ markerWidth / 2 ,
204+ markerWidth + spacing1 ,
205+ markerWidth + labelWidth + spacing1 + spacing2 ,
206+ markerWidth + labelWidth + valueWidth + spacing1 + spacing2 + spacing3 + focusWidth / 2 ,
207+ ] ,
188208 } ;
189209 }
190210
@@ -280,6 +300,49 @@ export class CategoryItem extends Component<CategoryItemStyleProps> {
280300 } ) ;
281301 }
282302
303+ private renderFocus ( ctn : Selection ) {
304+ const { focus, focusMarkerSize } = this . attributes ;
305+ const defaultOptions = {
306+ x : 0 ,
307+ y : 0 ,
308+ size : focusMarkerSize ,
309+ opacity : 0.6 ,
310+ symbol : 'focus' ,
311+ stroke : '#aaaaaa' ,
312+ lineWidth : 1 ,
313+ } ;
314+
315+ if ( isUndefined ( focus ) ) return ;
316+
317+ this . focusGroup = ctn . maybeAppendByClassName < Group > ( CLASS_NAMES . focusGroup , 'g' ) . style ( 'zIndex' , 0 ) ;
318+ ifShow ( focus , this . focusGroup , ( ) => {
319+ const marker = new Marker ( {
320+ style : {
321+ ...defaultOptions ,
322+ symbol : 'focus' ,
323+ } ,
324+ } ) ;
325+ const interactiveCircle = new Circle ( {
326+ style : {
327+ r : defaultOptions . size / 2 ,
328+ fill : 'transparent' ,
329+ } ,
330+ } ) ;
331+
332+ const container = this . focusGroup . node ( ) ;
333+ container . appendChild ( interactiveCircle ) ;
334+ container . appendChild ( marker ) ;
335+ marker . update ( { opacity : 0 } ) ;
336+
337+ ctn . node ( ) . addEventListener ( 'pointerenter' , ( ) => {
338+ marker . update ( { opacity : 1 } ) ;
339+ } ) ;
340+ ctn . node ( ) . addEventListener ( 'pointerleave' , ( ) => {
341+ marker . update ( { opacity : 0 } ) ;
342+ } ) ;
343+ } ) ;
344+ }
345+
283346 private renderPoptip ( ctn : Selection ) {
284347 const { poptip } = this . attributes ;
285348 if ( ! poptip ) return ;
@@ -305,7 +368,7 @@ export class CategoryItem extends Component<CategoryItemStyleProps> {
305368 labelWidth,
306369 valueWidth,
307370 height,
308- position : [ markerX , labelX , valueX ] ,
371+ position : [ markerX , labelX , valueX , focusX ] ,
309372 } ,
310373 } = this ;
311374 const halfHeight = height / 2 ;
@@ -316,6 +379,7 @@ export class CategoryItem extends Component<CategoryItemStyleProps> {
316379 transform : `translate(${ markerX } , ${ halfHeight } )${ this . markerGroup . node ( ) . style . _transform } ` ,
317380 } ) ;
318381 this . labelGroup . styles ( { transform : `translate(${ labelX } , ${ halfHeight } )` } ) ;
382+ if ( this . focusGroup ) this . focusGroup . styles ( { transform : `translate(${ focusX } , ${ halfHeight } )` } ) ;
319383
320384 ellipsisIt ( this . labelGroup . select ( CLASS_NAMES . label . class ) . node ( ) , Math . ceil ( labelWidth ) ) ;
321385 if ( this . showValue ) {
@@ -333,6 +397,7 @@ export class CategoryItem extends Component<CategoryItemStyleProps> {
333397 this . renderValue ( ctn ) ;
334398 this . renderBackground ( ctn ) ;
335399 this . renderPoptip ( ctn ) ;
400+ this . renderFocus ( ctn ) ;
336401 this . adjustLayout ( ) ;
337402 }
338403}
0 commit comments