1
- import { Category , Layout , Selection } from '@antv/component' ;
1
+ import { Category , Selection } from '@antv/component' ;
2
2
import { CategoryStyleProps } from '@antv/component/lib/ui/legend/types' ;
3
+ import { Canvas } from '@antv/g' ;
3
4
import { get , isFunction } from '@antv/util' ;
4
5
import { GraphEvent } from '../constants' ;
5
6
import type { RuntimeContext } from '../runtime/types' ;
6
7
import type { ElementDatum , ElementType , ID , State } from '../types' ;
7
8
import type { CardinalPlacement } from '../types/placement' ;
8
9
import type { BasePluginOptions } from './base-plugin' ;
9
10
import { BasePlugin } from './base-plugin' ;
11
+ import { createPluginCanvas } from './utils/canvas' ;
10
12
11
13
interface Datum extends Record < string , any > {
12
14
id ?: string ;
@@ -40,6 +42,24 @@ export interface LegendOptions extends BasePluginOptions, Omit<CategoryStyleProp
40
42
* @defaultValue 'bottom'
41
43
*/
42
44
position ?: CardinalPlacement ;
45
+ /**
46
+ * <zh/> 图例挂载的容器,无则挂载到 Graph 所在容器
47
+ *
48
+ * <en/> The container where the legend is mounted, if not, it will be mounted to the container where the Graph is located
49
+ */
50
+ container ?: HTMLElement | string ;
51
+ /**
52
+ * <zh/> 图例画布类名,传入外置容器时不生效
53
+ *
54
+ * <en/> The class name of the legend canvas, which does not take effect when an external container is passed in
55
+ */
56
+ className ?: string ;
57
+ /**
58
+ * <zh/> 图例的容器样式,传入外置容器时不生效
59
+ *
60
+ * <en/> The style of the legend container, which does not take effect when an external container is passed in
61
+ */
62
+ containerStyle ?: Partial < CSSStyleDeclaration > ;
43
63
/**
44
64
* <zh/> 节点分类标识
45
65
*
@@ -80,16 +100,20 @@ export class Legend extends BasePlugin<LegendOptions> {
80
100
colPadding : 10 ,
81
101
itemMarkerSize : 16 ,
82
102
itemLabelFontSize : 16 ,
103
+ width : 240 ,
104
+ height : 160 ,
83
105
} ;
84
106
private typePrefix = '__data__' ;
85
- private element : Layout | null = null ;
86
107
private draw = false ;
87
108
private fieldMap = {
88
109
node : new Map < string , ID [ ] > ( ) ,
89
110
edge : new Map < string , ID [ ] > ( ) ,
90
111
combo : new Map < string , ID [ ] > ( ) ,
91
112
} ;
92
113
private selectedItems : string [ ] = [ ] ;
114
+ private category ?: Category ;
115
+ private container ?: HTMLElement ;
116
+ private canvas ?: Canvas ;
93
117
94
118
constructor ( context : RuntimeContext , options : LegendOptions ) {
95
119
super ( context , Object . assign ( { } , Legend . defaultOptions , options ) ) ;
@@ -110,8 +134,11 @@ export class Legend extends BasePlugin<LegendOptions> {
110
134
}
111
135
112
136
private clear ( ) {
113
- this . element ?. destroy ( ) ;
114
- this . element = null ;
137
+ this . canvas ?. destroy ( ) ;
138
+ this . container ?. remove ( ) ;
139
+ this . canvas = undefined ;
140
+ this . container = undefined ;
141
+
115
142
this . draw = false ;
116
143
}
117
144
@@ -184,10 +211,9 @@ export class Legend extends BasePlugin<LegendOptions> {
184
211
* <en/> Refresh the status of the legend element
185
212
*/
186
213
public updateElement ( ) {
187
- if ( ! this . element ) return ;
188
- const category = this . element . getChildByIndex ( 0 ) as Category ;
214
+ if ( ! this . category ) return ;
189
215
190
- category . update ( {
216
+ this . category . update ( {
191
217
itemMarkerOpacity : ( { id } ) => {
192
218
if ( ! this . selectedItems . length || this . selectedItems . includes ( id ) ) return 1 ;
193
219
return 0.5 ;
@@ -224,7 +250,7 @@ export class Legend extends BasePlugin<LegendOptions> {
224
250
225
251
private getMarkerData = ( field : string | ( ( item : ElementDatum ) => string ) , elementType : ElementType ) => {
226
252
if ( ! field ) return [ ] ;
227
- const { model, element, graph } = this . context ;
253
+ const { model, element } = this . context ;
228
254
const { nodes, edges, combos } = model . getData ( ) ;
229
255
const items : { [ key : string ] : Datum } = { } ;
230
256
@@ -239,7 +265,8 @@ export class Legend extends BasePlugin<LegendOptions> {
239
265
combo : 'rect' ,
240
266
} ;
241
267
242
- /** 用于将 G6 element 转换为 componets 支持的类型 */
268
+ // 用于将 G6 element 转换为 components 支持的类型
269
+ // Used to convert G6 element to types supported by components
243
270
const markerMapping : { [ key : string ] : string } = {
244
271
circle : 'circle' ,
245
272
ellipse : 'circle' , // 待 components 支持 ellipse
@@ -303,69 +330,52 @@ export class Legend extends BasePlugin<LegendOptions> {
303
330
return Object . values ( items ) ;
304
331
} ;
305
332
306
- /**
307
- * <zh/> 图例布局
308
- *
309
- * <en/> Legend layout
310
- * @param position - <zh/> 图例位置| <en/> Legend position
311
- * @returns <zh/> 图例布局样式| <en/> Legend layout style
312
- */
313
- public layout = ( position : CardinalPlacement ) => {
314
- const preset = {
315
- flexDirection : 'row' ,
316
- alignItems : 'flex-end' ,
317
- justifyContent : 'center' ,
318
- } ;
319
- let { flexDirection, alignItems, justifyContent } = preset ;
333
+ private upsertCanvas ( ) {
334
+ if ( this . canvas ) return this . canvas ;
320
335
321
- const layout = {
322
- top : [ 'row' , 'flex-start' , 'center' ] ,
323
- bottom : [ 'row' , 'flex-end' , 'center' ] ,
324
- left : [ 'column' , 'flex-start' , 'center' ] ,
325
- right : [ 'column' , 'flex-end' , 'center' ] ,
326
- } ;
336
+ const graphCanvas = this . context . canvas ;
337
+ const [ canvasWidth , canvasHeight ] = graphCanvas . getSize ( ) ;
327
338
328
- if ( position in layout ) {
329
- [ flexDirection , alignItems , justifyContent ] = layout [ position ] ;
330
- }
331
- return {
332
- display : 'flex' ,
333
- flexDirection,
334
- justifyContent,
335
- alignItems,
336
- } ;
337
- } ;
339
+ const { width = canvasWidth , height = canvasHeight , position, container, containerStyle, className } = this . options ;
340
+ const [ $container , canvas ] = createPluginCanvas ( {
341
+ width,
342
+ height,
343
+ graphCanvas,
344
+ container,
345
+ containerStyle,
346
+ placement : position ,
347
+ className : 'legend' ,
348
+ } ) ;
349
+
350
+ this . container = $container ;
351
+ if ( className ) $container . classList . add ( className ) ;
352
+ this . canvas = canvas ;
353
+
354
+ return this . canvas ;
355
+ }
338
356
339
357
private createElement = ( ) => {
340
358
if ( this . draw ) {
341
359
this . updateElement ( ) ;
342
360
return ;
343
361
}
344
- const { canvas } = this . context ;
345
- const [ canvasWidth , canvasHeight ] = canvas . getSize ( ) ;
346
362
const {
347
- width = canvasWidth ,
348
- height = canvasHeight ,
363
+ width,
364
+ height,
349
365
nodeField,
350
366
edgeField,
351
367
comboField,
352
368
trigger,
353
369
position,
370
+ container,
371
+ containerStyle,
372
+ className,
354
373
...rest
355
374
} = this . options ;
356
375
const nodeItems = this . getMarkerData ( nodeField , 'node' ) ;
357
376
const edgeItems = this . getMarkerData ( edgeField , 'edge' ) ;
358
377
const comboItems = this . getMarkerData ( comboField , 'combo' ) ;
359
378
const items = [ ...nodeItems , ...comboItems , ...edgeItems ] ;
360
- const layout = this . layout ( position ) ;
361
-
362
- const layoutWrapper = new Layout ( {
363
- style : {
364
- width,
365
- height,
366
- ...layout ,
367
- } ,
368
- } ) ;
369
379
370
380
const categoryStyle = Object . assign (
371
381
{
@@ -386,9 +396,11 @@ export class Legend extends BasePlugin<LegendOptions> {
386
396
className : 'legend' ,
387
397
style : categoryStyle ,
388
398
} ) ;
389
- layoutWrapper . appendChild ( category ) ;
390
- canvas . appendChild ( layoutWrapper as any ) ;
391
- this . element = layoutWrapper ;
399
+ this . category = category ;
400
+
401
+ const canvas = this . upsertCanvas ( ) ;
402
+ canvas . appendChild ( category ) ;
403
+
392
404
this . draw = true ;
393
405
} ;
394
406
0 commit comments