- 说明
项目中需要绘制作业血缘图,网上调研了下也没有找到合适的轮子,于是就自己撸了,这里只有一层依赖关系,及父与子作业。 - 思路
根据后端返回的接口数据,计算每个节点的位置坐标,根据节点文本内容计算每个节点的宽度,高度固定。得到这些位置信息后,借用svg的path标签绘制出本依赖关系图。 - 预览
- 实现(代码写得比较粗糙,需要整体,这里贴个初版)
接口返回的数据结构如下:
代码实现:
// dag.js
const SVG_NS = 'http://www.w3.org/2000/svg'
export const getTextWidth = text => {
let svg = document.createElementNS(SVG_NS, 'svg')
let oText = document.createElementNS(SVG_NS, 'text')
oText.innerHTML = text
svg.appendChild(oText)
document.body.appendChild(svg)
let width = oText.getBBox().width
document.body.removeChild(svg)
return width + 10
}
// 创建tag标签
export const createTag = (tag, attrObjs) => {
let tagEle = document.createElementNS(SVG_NS, tag)
for (let key in attrObjs) {
tagEle.setAttribute(key, attrObjs[key])
}
return tagEle
}
// node类
class DagNode {
constructor (job = {
}, options = {
}, containerId) {
this.prev = []
this.next = []
this.job = job
this.width = Math.max(getTextWidth(job.jobName || job.jobId), 100)
this.height = 40
this.offsetX = options.offsetX || 0
this.offsetY = options.offsetY || 0
this.containerId = containerId || 'bloodChart'
}
// 绘制node
drawNode () {
let oG = createTag('g')
let oRect = createTag('rect', {
x: this.offsetX,
y: this.offsetY,
rx: 5,
ry: 5,
width: this.width,
height: this.height,
style: 'cursor: pointer; fill: transparent; stroke-width: 2; stroke: #303030'
})
let oText = createTag('text', {
x: this.offsetX + 10,
y: this.offsetY + 15,
style: `cursor: pointer; fill: #303030`,
'data-node': JSON.stringify(this.job)
})
let tSpan = createTag('tspan', {
x: this.offsetX + 10,
y: this.offsetY + 15,
style: `cursor: pointer; fill: #303030`,
'data-node': JSON.stringify(this.job)
})
tSpan.innerHTML = `${
this.job.jobName || this.job.jobId}`
let tSpan2 = createTag('tspan', {
x: this.offsetX + 10,
y: this.offsetY + 35,
style: `cursor: pointer; font-size: 12px; fill: #303030`,
'data-node': JSON.stringify(this.job)
})
tSpan2.innerHTML = `${
this.job.jobTypeCn} /