fileOverview author huangtonger aliyun import { IGroup , IShape , IElement } from '@antv/g-base' ; import { isArray , isNil , mix } from '@antv/util' ; import { ILabelConfig , ShapeOptions } from '../interface/shape' ; import { Item , LabelStyle , NodeConfig , ModelConfig , UpdateType } from '../types' ; import { formatPadding } from '../util/base' ; import Global from '../global' ; import Shape from './shape' ; import { shapeBase } from './shapeBase' ; const singleNode = { itemType : 'node' , shapeType : 'single-node' , type { String } labelPosition : 'center' , type { Number } offset : Global . nodeLabel . offset , internal param { Object } cfg return { Array } getSize ( cfg ) { let size = this . mergeStyle ?. size || cfg . size || this . getOptions ( { } ) ! . size || Global . defaultNode . size ; if ( isArray ( size ) && size . length === 1 ) { size = [ size [ 0 ] , size [ 0 ] ] ; } if ( ! isArray ( size ) ) { size = [ size , size ] ; } return size ; } , getLabelStyleByPosition ( cfg , labelCfg ) { const labelPosition = labelCfg . position || this . labelPosition ; if ( labelPosition === 'center' ) { return { x : 0 , y : 0 , text : cfg ! . label as string } ; } let { offset } = labelCfg ; if ( isNil ( offset ) ) { offset = this . offset as number ; } const size = this . getSize ! ( cfg as ModelConfig ) ; let style ; switch ( labelPosition ) { case 'top' : style = { x : 0 , y : - size [ 1 ] / 2 - ( offset as number ) , textBaseline : 'bottom' , } ; break ; case 'bottom' : style = { x : 0 , y : size [ 1 ] / 2 + ( offset as number ) , textBaseline : 'top' , } ; break ; case 'left' : style = { x : - size [ 0 ] / 2 - ( offset as number ) , y : 0 , textAlign : 'right' , } ; break ; default : style = { x : size [ 0 ] / 2 + ( offset as number ) , y : 0 , textAlign : 'left' , } ; break ; } style . text = cfg . label ; return style ; } , getLabelBgStyleByPosition ( label , labelCfg ? ) { if ( ! label ) return { } ; const backgroundStyle = labelCfg . style ?. background ; if ( ! backgroundStyle ) return { } ; const bbox = label . getBBox ( ) ; const padding = formatPadding ( backgroundStyle . padding ) ; const backgroundWidth = bbox . width + padding [ 1 ] + padding [ 3 ] ; const backgroundHeight = bbox . height + padding [ 0 ] + padding [ 2 ] ; return { x : bbox . minX - padding [ 3 ] , y : bbox . minY - padding [ 0 ] , ... backgroundStyle , width : backgroundWidth , height : backgroundHeight , } ; } , drawShape ( cfg , group ) { const { shapeType } = this ; const style = this . getShapeStyle ! ( cfg ) ; const shape = group . addShape ( shapeType , { attrs : style , draggable : true , name : 'node-shape' , } ) ; group [ 'shapeMap' ] [ 'node-shape' ] = shape ; return shape ; } , param { Object } cfg param { Group } group updateLinkPoints ( cfg , group ) { const { linkPoints : defaultLinkPoints } = this . mergeStyle || this . getOptions ( cfg ) as ModelConfig ; const markLeft = group [ 'shapeMap' ] [ 'link-point-left' ] || group . find ( ( element ) => element . get ( 'className' ) === 'link-point-left' ) ; const markRight = group [ 'shapeMap' ] [ 'link-point-right' ] || group . find ( ( element ) => element . get ( 'className' ) === 'link-point-right' ) ; const markTop = group [ 'shapeMap' ] [ 'link-point-top' ] || group . find ( ( element ) => element . get ( 'className' ) === 'link-point-top' ) ; const markBottom = group [ 'shapeMap' ] [ 'link-point-bottom' ] || group . find ( ( element ) => element . get ( 'className' ) === 'link-point-bottom' ) ; let currentLinkPoints ; if ( markLeft ) { currentLinkPoints = markLeft . attr ( ) ; } if ( markRight && ! currentLinkPoints ) { currentLinkPoints = markRight . attr ( ) ; } if ( markTop && ! currentLinkPoints ) { currentLinkPoints = markTop . attr ( ) ; } if ( markBottom && ! currentLinkPoints ) { currentLinkPoints = markBottom . attr ( ) ; } if ( ! currentLinkPoints ) currentLinkPoints = defaultLinkPoints ; const linkPoints = mix ( { } , currentLinkPoints , cfg . linkPoints ) ; const { fill : markFill , stroke : markStroke , lineWidth : borderWidth } = linkPoints ; let markSize = linkPoints . size / 2 ; if ( ! markSize ) markSize = linkPoints . r ; const { left , right , top , bottom } = cfg . linkPoints ? cfg . linkPoints : { left : undefined , right : undefined , top : undefined , bottom : undefined } ; const size = this . getSize ! ( cfg ) ; const width = size [ 0 ] ; const height = size [ 1 ] ; const styles = { r : markSize , fill : markFill , stroke : markStroke , lineWidth : borderWidth , } ; if ( markLeft ) { if ( ! left && left !== undefined ) { markLeft . remove ( ) ; delete group [ 'shapeMap' ] [ 'link-point-left' ] ; } else { markLeft . attr ( { ... styles , x : - width / 2 , y : 0 , } ) ; } } else if ( left ) { const name = 'link-point-left' ; group [ 'shapeMap' ] [ name ] = group . addShape ( 'circle' , { attrs : { ... styles , x : - width / 2 , y : 0 , } , className : name , name , isAnchorPoint : true , } ) ; } if ( markRight ) { if ( ! right && right !== undefined ) { markRight . remove ( ) ; delete group [ 'shapeMap' ] [ 'link-point-right' ] ; } markRight . attr ( { ... styles , x : width / 2 , y : 0 , } ) ; } else if ( right ) { const name = 'link-point-right' ; group [ 'shapeMap' ] [ name ] = group . addShape ( 'circle' , { attrs : { ... styles , x : width / 2 , y : 0 , } , className : name , name , isAnchorPoint : true , } ) ; } if ( markTop ) { if ( ! top && top !== undefined ) { markTop . remove ( ) ; delete group [ 'shapeMap' ] [ 'link-point-top' ] ; } markTop . attr ( { ... styles , x : 0 , y : - height / 2 , } ) ; } else if ( top ) { const name = 'link-point-top' ; group [ 'shapeMap' ] [ name ] = group . addShape ( 'circle' , { attrs : { ... styles , x : 0 , y : - height / 2 , } , className : name , name , isAnchorPoint : true , } ) ; } if ( markBottom ) { if ( ! bottom && bottom !== undefined ) { markBottom . remove ( ) ; delete group [ 'shapeMap' ] [ 'link-point-bottom' ] ; } else { markBottom . attr ( { ... styles , x : 0 , y : height / 2 , } ) ; } } else if ( bottom ) { const name = 'link-point-bottom' ; group [ 'shapeMap' ] [ name ] = group . addShape ( 'circle' , { attrs : { ... styles , x : 0 , y : height / 2 , } , className : name , name , isAnchorPoint : true , } ) ; } } , updateShape ( cfg , item , keyShapeStyle , hasIcon , updateType ) { const keyShape = item . get ( 'keyShape' ) ; keyShape . attr ( { ... keyShapeStyle , } ) ; if ( ! undefined || updateType ?. includes ( 'label' ) ) { ( this as any ) . updateLabel ( cfg , item , updateType ) ; } if ( hasIcon ) { ( this as any ) . updateIcon ( cfg , item ) ; } } , updateIcon ( cfg , item ) { const group = item . getContainer ( ) ; const { icon } = this . mergeStyle || this . getOptions ( cfg ) as NodeConfig ; const { show , text } = cfg . icon ? cfg . icon : { show : undefined , text : undefined } ; const iconShape = group [ 'shapeMap' ] [ `${ this . type }-icon` ] || group . find ( ele => ele . get ( 'name' ) === `${ this . type }-icon` ) ; if ( iconShape ) { if ( show || show === undefined ) { const iconConfig = mix ( { } , iconShape . attr ( ) , icon ) ; let { width : w = 20 , height : h = 20 } = iconConfig ; if ( iconConfig . fontFamily === 'iconfont' || iconConfig . hasOwnProperty ( 'text' ) ) { w = 0 ; h = 0 ; } iconShape . attr ( { ... iconConfig , x : - w / 2 , y : - h / 2 , } ) ; } else { iconShape . remove ( ) ; } } else if ( show ) { const name = `${ this . type }-icon` ; if ( text ) { group [ 'shapeMap' ] [ name ] = group . addShape ( 'text' , { attrs : { x : 0 , y : 0 , fontSize : 12 , fill : '#000' , stroke : '#000' , textBaseline : 'middle' , textAlign : 'center' , ... icon , } , className : name , name , } ) ; } else { let { width : w , height : h } = icon ; group [ 'shapeMap' ] [ name ] = group . addShape ( 'image' , { attrs : { ... icon , x : - w ! / 2 , y : - h ! / 2 , } , className : name , name , } ) ; } const labelShape = group [ 'shapeMap' ] [ 'node-label' ] || group . find ( ele => ele . get ( 'name' ) === 'node-label' ) ; if ( labelShape ) { labelShape . toFront ( ) ; } } } , } ; const singleNodeDef = { ... shapeBase , ... singleNode } ; Shape . registerNode ( 'single-node' , singleNodeDef ) ;