author ChicAboo
 *  date import { FlowElement , EdgeTypes , NodeTypes , XYPosition , IndexProps , Rect , Box , Dimensions , } from '@/typings' ; import { config } from '@/constants/config' ; export const isEdge = ( element ) : element is EdgeTypes => 'id' in element && 'source' in element && 'target' in element ; export const isNode = ( element ) : element is NodeTypes => 'id' in element && ! ( 'source' in element ) && ! ( 'target' in element ) ; export const parseElement = ( element ) : NodeTypes | EdgeTypes => { if ( ! element . id ) { throw new Error ( 'All nodes and edges need to have an id.' ) ; } if ( isEdge ( element ) ) { return { ... element , sourceId : element . sourceId . toString ( ) , targetId : element . targetId . toString ( ) , id : element . id . toString ( ) , } ; } return { ... element , id : element . id . toString ( ) , } as NodeTypes ; } ; param param export function _position ( x , y , direction ) { const { width , height } = config . rect ; const point = { x : x , y : y , } ; switch ( direction ) { case 'left' : point . x = x - width / 2 ; point . y = y ; break ; case 'right' : point . x = x + width / 2 ; point . y = y ; break ; case 'top' : point . x = x ; point . y = y - height / 2 ; break ; case 'bottom' : point . x = x ; point . y = y + height / 2 ; break ; } return point ; } param param export function coverNode ( x , y , nodes ) { const res = { } ; const { width , height , distance } = config . rect ; const length = nodes . length ; if ( nodes && length === 0 ) { return { } ; } for ( let i = 0 ; i < length ; i ++ ) { const item = nodes [ i ] ; const position = item . position ; if ( x >= position . x - width / 2 - distance && x <= position . x + width / 2 + distance && y >= position . y - height / 2 - distance && y <= position . y + height / 2 + distance ) { res . exists = true ; res . x = position . x ; res . y = position . y ; res . targetId = item . id ; res . direction = finishPosition ( x , y , position . x , position . y ) ; } } return res ; } param param return function finishPosition ( x1 , y1 , x2 , y2 ) { const { width , height } = config . rect ; const disArr = [ ] ; const obj = { } ; const coordinate = { left : { x : x2 - width / 2 , y : y2 } , right : { x : x2 + width / 2 , y : y2 } , top : { x : x2 , y : y2 - height / 2 } , bottom : { x : x2 , y : y2 + height / 2 } , } ; Object . keys ( coordinate ) . forEach ( ( key ) => { const powX = Math . pow ( Math . abs ( x1 - coordinate [ key ] . x ) , 2 ) ; const powY = Math . pow ( Math . abs ( y1 - coordinate [ key ] . y ) , 2 ) ; const distance = Math . sqrt ( powX + powY ) ; disArr . push ( distance ) ; obj [ distance ] = key ; } ) ; return obj [ Math . min ( ... disArr ) ] ; } param startPoint param endPoint param startDirection param endDirection export function offsetFn ( startPoint , endPoint , startDirection , endDirection ) { const positionStart = _position ( startPoint . x , startPoint . y , startDirection ) ; const positionEnd = _position ( endPoint . x , endPoint . y , endDirection ) ; return { x1 : positionStart . x , y1 : positionStart . y , x2 : positionEnd . x , y2 : positionEnd . y , startDirection : startDirection , endDirection : endDirection , } ; } param { * } position param startId param endId export function linePath ( position , startId , endId ) { const { x1 , y1 , x2 , y2 , startDirection , endDirection } = position ; const { width } = config . rect ; const sourceMiddle = middlePath ( x1 , y1 , startDirection ) ; const middleX1 = sourceMiddle . x ; const middleY1 = sourceMiddle . y ; const targetMiddle = middlePath ( x2 , y2 , endDirection ) ; const middleX2 = targetMiddle . x ; const middleY2 = targetMiddle . y ; let middleX = ( middleX1 + middleX2 ) / 2 ; let middleY = middleY1 ; if ( startId === endId ) { if ( startDirection === 'top' || startDirection === 'bottom' ) { middleX = middleX1 + width ; if ( endDirection === 'left' ) { middleX = middleX1 - width ; } } else if ( startDirection === 'left' || startDirection === 'right' ) { middleX = middleX1 ; } } else { if ( ( startDirection === 'left' && endDirection === 'left' ) || ( startDirection === 'right' && endDirection === 'right' ) ) { middleX = middleX1 ; middleY = middleY2 ; } else { } } return { middleX : middleX , middleY : ( middleY1 + middleY2 ) / 2 , pathData : `
      M ${ x1 }, ${ y1 }
      L ${ middleX1 }, ${ middleY1 }
      L ${ middleX }, ${ middleY }
      L ${ middleX }, ${ middleY2 }
      L ${ middleX2 }, ${ middleY2 }
      L ${ x2 }, ${ y2 }
    ` , } ; } param { * } x param { * } y param { * } direction function middlePath ( x , y , direction ) { const res = { } ; switch ( direction ) { case 'left' : res . x = x - config . path . middleDistance ; res . y = y ; break ; case 'top' : res . x = x ; res . y = y - config . path . middleDistance ; break ; case 'right' : res . x = x + config . path . middleDistance ; res . y = y ; break ; case 'bottom' : res . x = x ; res . y = y + config . path . middleDistance ; break ; default : res . x = x ; res . y = y ; break ; } return res ; } const getBoundsOfBoxes = ( box1 , box2 ) : Box => ( { x : Math . min ( box1 . x , box2 . x ) , y : Math . min ( box1 . y , box2 . y ) , x2 : Math . max ( box1 . x2 , box2 . x2 ) , y2 : Math . max ( box1 . y2 , box2 . y2 ) , } ) ; export const rectToBox = ( { x , y , width , height } ) : Box => ( { x , y , x2 : x + width , y2 : y + height , } ) ; export const boxToRect = ( { x , y , x2 , y2 } ) : Rect => ( { x , y , width : x2 - x , height : y2 - y , } ) ; /**
 *  获取图形的宽高
 * */ export const getRectOfNodes = ( nodes ) : Rect => { const { width , height } = config . rect ; const box = nodes . reduce ( ( currBox , { position } ) => { return getBoundsOfBoxes ( currBox , rectToBox ( { x : position . x , y : position . y , width , height } ) ) ; } , { x : Infinity , y : Infinity , x2 : - Infinity , y2 : - Infinity } ) ; return boxToRect ( box ) ; } ; export const clamp = ( val , min = 0 , max = 1 ) : number => Math . min ( Math . max ( val , min ) , max ) ; export const getDimensions = ( node ) : Dimensions => ( { width : node . offsetWidth , height : node . offsetHeight , } ) ;