UNPKG

@antv/x6

Version:

JavaScript diagramming library that uses SVG and HTML for rendering

178 lines (161 loc) 3.62 kB
import type { Point, Rectangle } from '../../geometry' import type { PortLabelLayoutCommonOptions, PortLabelLayoutDefinition, } from './index' import { toResult } from './util' export interface InOutArgs extends PortLabelLayoutCommonOptions { offset?: number } export const outside: PortLabelLayoutDefinition<InOutArgs> = ( portPosition, elemBBox, args, ) => outsideLayout(portPosition, elemBBox, false, args) export const outsideOriented: PortLabelLayoutDefinition<InOutArgs> = ( portPosition, elemBBox, args, ) => outsideLayout(portPosition, elemBBox, true, args) export const inside: PortLabelLayoutDefinition<InOutArgs> = ( portPosition, elemBBox, args, ) => insideLayout(portPosition, elemBBox, false, args) export const insideOriented: PortLabelLayoutDefinition<InOutArgs> = ( portPosition, elemBBox, args, ) => insideLayout(portPosition, elemBBox, true, args) function outsideLayout( portPosition: Point, elemBBox: Rectangle, autoOrient: boolean, args: InOutArgs, ) { const offset = args.offset != null ? args.offset : 15 const angle = elemBBox.getCenter().theta(portPosition) const bboxAngles = getBBoxAngles(elemBBox) let y let tx let ty let textAnchor let orientAngle = 0 if (angle < bboxAngles[1] || angle > bboxAngles[2]) { y = '.3em' tx = offset ty = 0 textAnchor = 'start' } else if (angle < bboxAngles[0]) { y = '0' tx = 0 ty = -offset if (autoOrient) { orientAngle = -90 textAnchor = 'start' } else { textAnchor = 'middle' } } else if (angle < bboxAngles[3]) { y = '.3em' tx = -offset ty = 0 textAnchor = 'end' } else { y = '.6em' tx = 0 ty = offset if (autoOrient) { orientAngle = 90 textAnchor = 'start' } else { textAnchor = 'middle' } } return toResult( { position: { x: Math.round(tx), y: Math.round(ty), }, angle: orientAngle, attrs: { '.': { y, 'text-anchor': textAnchor, }, }, }, args, ) } function insideLayout( portPosition: Point, elemBBox: Rectangle, autoOrient: boolean, args: InOutArgs, ) { const offset = args.offset != null ? args.offset : 15 const angle = elemBBox.getCenter().theta(portPosition) const bboxAngles = getBBoxAngles(elemBBox) let y let tx let ty let textAnchor let orientAngle = 0 if (angle < bboxAngles[1] || angle > bboxAngles[2]) { y = '.3em' tx = -offset ty = 0 textAnchor = 'end' } else if (angle < bboxAngles[0]) { y = '.6em' tx = 0 ty = offset if (autoOrient) { orientAngle = 90 textAnchor = 'start' } else { textAnchor = 'middle' } } else if (angle < bboxAngles[3]) { y = '.3em' tx = offset ty = 0 textAnchor = 'start' } else { y = '0em' tx = 0 ty = -offset if (autoOrient) { orientAngle = -90 textAnchor = 'start' } else { textAnchor = 'middle' } } return toResult( { position: { x: Math.round(tx), y: Math.round(ty), }, angle: orientAngle, attrs: { '.': { y, 'text-anchor': textAnchor, }, }, }, args, ) } function getBBoxAngles(elemBBox: Rectangle) { const center = elemBBox.getCenter() const tl = center.theta(elemBBox.getTopLeft()) const bl = center.theta(elemBBox.getBottomLeft()) const br = center.theta(elemBBox.getBottomRight()) const tr = center.theta(elemBBox.getTopRight()) return [tl, tr, br, bl] }