@antv/x6
Version:
JavaScript diagramming library that uses SVG and HTML for rendering
178 lines (161 loc) • 3.62 kB
text/typescript
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]
}