Files
AgentCoord/src/layout/components/Main/TaskTemplate/utils.ts

170 lines
4.2 KiB
TypeScript
Raw Normal View History

import type {
AnchorSpec,
ConnectorSpec,
ConnectParams,
EndpointOptions,
JsPlumbInstance,
} from '@jsplumb/browser-ui'
import { BezierConnector, DotEndpoint, newInstance } from '@jsplumb/browser-ui'
export interface JsplumbConfig {
connector?: ConnectorSpec
type?: 'input' | 'output'
stops?: [[number, string], [number, string]]
// 连接线条是否变透明一些
transparent?: boolean
}
export interface ConnectArg {
sourceId: string
targetId: string
anchor: AnchorSpec
config?: JsplumbConfig
}
const defaultConfig: JsplumbConfig = {
connector: {
type: BezierConnector.type,
options: {
curviness: 70,
stub: 10,
},
},
type: 'input',
}
export class Jsplumb {
instance!: JsPlumbInstance
containerId: string
config: JsplumbConfig
constructor(eleId: string, config = {} as JsplumbConfig) {
this.containerId = eleId
this.config = { ...defaultConfig, ...config }
onMounted(() => {
this.init()
})
}
init = () => {
if (this.instance) {
return
}
this.instance = newInstance({
container: document.querySelector(`#${this.containerId}`)!, // 或指定共同的父容器
})
}
getStops = (type?: 'input' | 'output'): [[number, string], [number, string]] => {
if (type === 'input') {
return [
[0, '#FF6161'],
[1, '#D76976'],
]
}
return [
[0, '#0093EB'],
[1, '#00D2D1'],
]
}
_connect = (
sourceId: string,
targetId: string,
anchor: AnchorSpec,
_config = {} as JsplumbConfig,
) => {
const config = {
...defaultConfig,
...this.config,
..._config,
}
this.init()
// 连接两个元素
const sourceElement = document.querySelector(`#${sourceId}`)
const targetElement = document.querySelector(`#${targetId}`)
const stops = _config.stops ?? this.getStops(config.type)
// 如果config.transparent为true则将stops都加一些透明度
if (config.transparent) {
stops[0][1] = stops[0][1] + '30'
stops[1][1] = stops[1][1] + '30'
}
if (targetElement && sourceElement) {
this.instance.connect({
source: sourceElement,
target: targetElement,
connector: config.connector,
anchor: anchor,
paintStyle: {
stroke: stops[0][1],
strokeWidth: 2.5,
dashstyle: '0',
zIndex: 100,
opacity: 0.9,
gradient: {
stops: stops,
type: 'linear',
},
},
sourceEndpointStyle: { fill: stops[0][1] },
endpoint: {
type: DotEndpoint.type,
options: { radius: 5 },
},
cssClass: `jtk-connector-${config.type}`
} as unknown as ConnectParams<unknown>)
// 为源元素添加端点
this.instance.addEndpoint(sourceElement, {
anchor: (anchor as [AnchorSpec, AnchorSpec])[0],
paintStyle: { fill: stops[0][1], zIndex: 100 }, // source端点颜色
} as unknown as EndpointOptions)
// 为目标元素添加端点
this.instance.addEndpoint(targetElement, {
anchor: (anchor as [AnchorSpec, AnchorSpec])[1],
paintStyle: { fill: stops[1][1], zIndex: 100 }, // target端点颜色
} as unknown as EndpointOptions)
}
}
connect = (
sourceId: string,
targetId: string,
anchor: AnchorSpec,
config = {} as JsplumbConfig,
) => {
this._connect(sourceId, targetId, anchor, config)
}
connects = (args: ConnectArg[]) => {
this.instance.batch(() => {
args.forEach(({ sourceId, targetId, anchor, config }) => {
this._connect(sourceId, targetId, anchor, config)
})
})
}
repaintEverything = () => {
// 重新验证元素位置
const container = document.querySelector(`#${this.containerId}`)
if (container) {
const elements = container.querySelectorAll('[id^="task-results-"]')
elements.forEach((element) => {
this.instance.revalidate(element)
})
}
this.instance.repaintEverything()
}
reset = () => {
this.instance.deleteEveryConnection()
const allEndpoints = this.instance.selectEndpoints()
allEndpoints.each((endpoint) => {
this.instance.deleteEndpoint(endpoint)
})
}
}