Feat:节点连线支持显示箭头

This commit is contained in:
街角小林
2023-12-26 10:23:15 +08:00
parent 29c5075fa5
commit 80f8a357fe
11 changed files with 97 additions and 72 deletions

View File

@@ -187,7 +187,10 @@ class Node {
}
// 如果没有返回内容,那么还是使用内置的节点内容
if (this._customNodeContent) {
this._customNodeContent.setAttribute('xmlns', 'http://www.w3.org/1999/xhtml')
this._customNodeContent.setAttribute(
'xmlns',
'http://www.w3.org/1999/xhtml'
)
return
}
this._imgData = this.createImgNode()
@@ -831,9 +834,9 @@ class Node {
this.renderer.layout.renderLine(
this,
this._lines,
(line, node) => {
(...args) => {
// 添加样式
this.styleLine(line, node)
this.styleLine(...args)
},
this.style.getStyle('lineStyle', true)
)
@@ -888,19 +891,26 @@ class Node {
}
// 设置连线样式
styleLine(line, node) {
let width =
node.getSelfInhertStyle('lineWidth') || node.getStyle('lineWidth', true)
let color =
node.getSelfInhertStyle('lineColor') || node.getStyle('lineColor', true)
let dasharray =
node.getSelfInhertStyle('lineDasharray') ||
node.getStyle('lineDasharray', true)
this.style.line(line, {
width,
color,
dasharray
})
styleLine(line, childNode, enableMarker) {
const width =
childNode.getSelfInhertStyle('lineWidth') ||
childNode.getStyle('lineWidth', true)
const color =
childNode.getSelfInhertStyle('lineColor') ||
childNode.getStyle('lineColor', true)
const dasharray =
childNode.getSelfInhertStyle('lineDasharray') ||
childNode.getStyle('lineDasharray', true)
this.style.line(
line,
{
width,
color,
dasharray
},
enableMarker,
childNode
)
}
// 移除连线

View File

@@ -55,6 +55,9 @@ class Style {
// 构造函数
constructor(ctx) {
this.ctx = ctx
// 箭头图标
this._markerPath = null
this._marker = null
}
// 合并样式
@@ -190,8 +193,38 @@ class Style {
}
// 连线
line(node, { width, color, dasharray } = {}) {
node.stroke({ width, color, dasharray }).fill({ color: 'none' })
line(line, { width, color, dasharray } = {}, enableMarker, childNode) {
line.stroke({ color, dasharray, width }).fill({ color: 'none' })
// 可以显示箭头
if (enableMarker) {
const showMarker = this.merge('showLineMarker', true)
const childNodeStyle = childNode.style
// 显示箭头
if (showMarker) {
// 创建子节点箭头标记
childNodeStyle._marker =
childNodeStyle._marker || childNodeStyle.createMarker()
// 设置样式
childNodeStyle._markerPath.stroke({ color }).fill({ color })
line.marker('end', childNodeStyle._marker)
} else if (childNodeStyle._marker) {
// 不显示箭头,则删除该子节点的箭头标记
line.attr('marker-end', '')
childNodeStyle._marker.remove()
childNodeStyle._marker = null
}
}
}
// 创建箭头
createMarker() {
return this.ctx.lineDraw.marker(20, 20, add => {
add.ref(8, 5)
add.size(20, 20)
add.attr('markerUnits', 'userSpaceOnUse')
add.attr('orient', 'auto-start-reverse')
this._markerPath = add.path('M0,0 L2,5 L0,10 L10,5 Z')
})
}
// 概要连线

View File

@@ -443,6 +443,12 @@ class Base {
getNodeActChildrenLength(node) {
return node.nodeData.children && node.nodeData.children.length
}
// 设置连线样式
setLineStyle(style, line, path, childNode) {
line.plot(path)
style && style(line, childNode, true)
}
}
export default Base

View File

@@ -233,8 +233,7 @@ class CatalogOrganization extends Base {
`M ${x2},${y1 + s1} L ${x2},${y1 + s1 > y2 ? y2 + item.height : y2}` +
nodeUseLineStylePath
// 竖线
lines[index].plot(path)
style && style(lines[index], item)
this.setLineStyle(style, lines[index], path, item)
})
minx = Math.min(minx, x1)
maxx = Math.max(maxx, x1)
@@ -302,8 +301,7 @@ class CatalogOrganization extends Base {
}`
: ''
path += nodeUseLineStylePath
lines[index].plot(path)
style && style(lines[index], item)
this.setLineStyle(style, lines[index], path, item)
})
// 竖线
if (len > 0) {

View File

@@ -300,8 +300,7 @@ class Fishbone extends Base {
// 水平线
if (node.layerIndex > 1) {
let path = `M ${x},${y} L ${item.left},${y}`
lines[index].plot(path)
style && style(lines[index], item)
this.setLineStyle(style, lines[index], path, item)
}
})
// 斜线

View File

@@ -181,8 +181,7 @@ class LogicalStructure extends Base {
let path = `M ${x1},${y1} L ${x1 + s1},${y1} L ${x1 + s1},${y2} L ${
x2 + nodeUseLineStyleOffset
},${y2}`
lines[index].plot(path)
style && style(lines[index], item)
this.setLineStyle(style, lines[index], path, item)
})
}
@@ -209,8 +208,7 @@ class LogicalStructure extends Base {
? ` L ${item.left + item.width},${y2}`
: ''
let path = `M ${x1},${y1} L ${x2},${y2}` + nodeUseLineStylePath
lines[index].plot(path)
style && style(lines[index], item)
this.setLineStyle(style, lines[index], path, item)
})
}
@@ -242,8 +240,7 @@ class LogicalStructure extends Base {
} else {
path = this.cubicBezierPath(x1, y1, x2, y2) + nodeUseLineStylePath
}
lines[index].plot(path)
style && style(lines[index], item)
this.setLineStyle(style, lines[index], path, item)
})
}

View File

@@ -116,11 +116,7 @@ class MindMap extends Base {
this.root,
null,
(node, parent, isRoot, layerIndex) => {
if (
node.getData('expand') &&
node.children &&
node.children.length
) {
if (node.getData('expand') && node.children && node.children.length) {
let marginY = this.getMarginY(layerIndex + 1)
let baseTop = node.top + node.height / 2 + marginY
// 第一个子节点的top值 = 该节点中心的top值 - 子节点的高度之和的一半
@@ -247,8 +243,7 @@ class MindMap extends Base {
let path = `M ${x1},${y1} L ${x1 + _s},${y1} L ${x1 + _s},${y2} L ${
x2 + nodeUseLineStyleOffset
},${y2}`
lines[index].plot(path)
style && style(lines[index], item)
this.setLineStyle(style, lines[index], path, item)
})
}
@@ -287,8 +282,7 @@ class MindMap extends Base {
}
}
let path = `M ${x1},${y1} L ${x2},${y2}` + nodeUseLineStylePath
lines[index].plot(path)
style && style(lines[index], item)
this.setLineStyle(style, lines[index], path, item)
})
}
@@ -332,8 +326,7 @@ class MindMap extends Base {
} else {
path = this.cubicBezierPath(x1, y1, x2, y2) + nodeUseLineStylePath
}
lines[index].plot(path)
style && style(lines[index], item)
this.setLineStyle(style, lines[index], path, item)
})
}
@@ -384,7 +377,8 @@ class MindMap extends Base {
x +
(isLeft ? -generalizationNodeMargin : generalizationNodeMargin) -
(isLeft ? item.generalizationNode.width : 0)
item.generalizationNode.top = top + (bottom - top - item.generalizationNode.height) / 2
item.generalizationNode.top =
top + (bottom - top - item.generalizationNode.height) / 2
})
}

View File

@@ -78,11 +78,7 @@ class OrganizationStructure extends Base {
this.root,
null,
(node, parent, isRoot, layerIndex) => {
if (
node.getData('expand') &&
node.children &&
node.children.length
) {
if (node.getData('expand') && node.children && node.children.length) {
let marginX = this.getMarginY(layerIndex + 1)
// 第一个子节点的left值 = 该节点中心的left值 - 子节点的宽度之和的一半
let left = node.left + node.width / 2 - node.childrenAreaWidth / 2
@@ -175,8 +171,7 @@ class OrganizationStructure extends Base {
? ` L ${item.left},${y2} L ${item.left + item.width},${y2}`
: ''
let path = `M ${x1},${y1} L ${x2},${y2}` + nodeUseLineStylePath
lines[index].plot(path)
style && style(lines[index], item)
this.setLineStyle(style, lines[index], path, item)
})
}
@@ -210,8 +205,7 @@ class OrganizationStructure extends Base {
? ` L ${item.left},${y2} L ${item.left + item.width},${y2}`
: ''
let path = `M ${x2},${y1 + s1} L ${x2},${y2}` + nodeUseLineStylePath
lines[index].plot(path)
style && style(lines[index], item)
this.setLineStyle(style, lines[index], path, item)
})
minx = Math.min(x1, minx)
maxx = Math.max(x1, maxx)
@@ -261,9 +255,9 @@ class OrganizationStructure extends Base {
let path = `M ${x1},${y1} Q ${cx},${cy} ${x2},${y2}`
item.generalizationLine.plot(path)
item.generalizationNode.top = bottom + generalizationNodeMargin
item.generalizationNode.left = left + (right - left - item.generalizationNode.width) / 2
item.generalizationNode.left =
left + (right - left - item.generalizationNode.width) / 2
})
}
// 渲染展开收起按钮的隐藏占位元素

View File

@@ -245,8 +245,7 @@ class Timeline extends Base {
let x2 = item.left
let y = node.top + node.height / 2
let path = `M ${x1},${y} L ${x2},${y}`
lines[index].plot(path)
style && style(lines[index], item)
this.setLineStyle(style, lines[index], path, item)
prevBother = item
})
} else {
@@ -264,8 +263,7 @@ class Timeline extends Base {
}
// 水平线
let path = `M ${x},${y} L ${item.left},${y}`
lines[index].plot(path)
style && style(lines[index], item)
this.setLineStyle(style, lines[index], path, item)
})
// 竖线
if (len > 0) {

View File

@@ -246,8 +246,7 @@ class VerticalTimeline extends Base {
let y2 = item.top
let x = node.left + node.width / 2
let path = `M ${x},${y1} L ${x},${y2}`
lines[index].plot(path)
style && style(lines[index], item)
this.setLineStyle(style, lines[index], path, item)
prevBother = item
})
} else {
@@ -265,8 +264,7 @@ class VerticalTimeline extends Base {
L ${nodeRight + offset},${nodeYCenter}
L ${nodeRight + offset},${itemYCenter}
L ${itemLeft},${itemYCenter}`
lines[index].plot(path)
style && style(lines[index], item)
this.setLineStyle(style, lines[index], path, item)
})
} else {
let nodeLeft = node.left
@@ -281,8 +279,7 @@ class VerticalTimeline extends Base {
L ${nodeLeft - offset},${nodeYCenter}
L ${nodeLeft - offset},${itemYCenter}
L ${itemRight},${itemYCenter}`
lines[index].plot(path)
style && style(lines[index], item)
this.setLineStyle(style, lines[index], path, item)
})
}
}
@@ -306,8 +303,7 @@ class VerticalTimeline extends Base {
let y2 = item.top
let x = node.left + node.width / 2
let path = `M ${x},${y1} L ${x},${y2}`
lines[index].plot(path)
style && style(lines[index], item)
this.setLineStyle(style, lines[index], path, item)
prevBother = item
})
} else {
@@ -322,8 +318,7 @@ class VerticalTimeline extends Base {
: item.left
let y2 = item.top + item.height / 2
let path = `M ${x1},${y1} L ${x2},${y2}`
lines[index].plot(path)
style && style(lines[index], item)
this.setLineStyle(style, lines[index], path, item)
}
})
}
@@ -346,8 +341,7 @@ class VerticalTimeline extends Base {
let y2 = item.top
let x = node.left + node.width / 2
let path = `M ${x},${y1} L ${x},${y2}`
lines[index].plot(path)
style && style(lines[index], item)
this.setLineStyle(style, lines[index], path, item)
prevBother = item
})
} else {
@@ -362,8 +356,7 @@ class VerticalTimeline extends Base {
: item.left
let y2 = item.top + item.height / 2
let path = this.cubicBezierPath(x1, y1, x2, y2)
lines[index].plot(path)
style && style(lines[index], item)
this.setLineStyle(style, lines[index], path, item)
}
})
}

View File

@@ -20,6 +20,8 @@ export default {
lineStyle: 'straight', // 针对logicalStructure、mindMap两种结构。曲线curve、直线straight、直连direct
// 曲线连接时,根节点和其他节点的连接线样式保持统一,默认根节点为 ( 型,其他节点为 { 型设为true后都为 { 型
rootLineKeepSameInCurve: true,
// 连线尾部是否显示标记,目前只支持箭头
showLineMarker: false,
// 概要连线的粗细
generalizationLineWidth: 1,
// 概要连线的颜色
@@ -159,7 +161,8 @@ const nodeSizeIndependenceList = [
'backgroundRepeat',
'backgroundPosition',
'backgroundSize',
'rootLineKeepSameInCurve'
'rootLineKeepSameInCurve',
'showLineMarker'
]
export const checkIsNodeSizeIndependenceConfig = config => {
let keys = Object.keys(config)