mirror of
https://github.com/wanglin2/mind-map.git
synced 2026-02-17 22:08:25 +08:00
Feat:节点连线支持显示箭头
This commit is contained in:
@@ -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
|
||||
)
|
||||
}
|
||||
|
||||
// 移除连线
|
||||
|
||||
@@ -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')
|
||||
})
|
||||
}
|
||||
|
||||
// 概要连线
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
})
|
||||
// 斜线
|
||||
|
||||
@@ -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)
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
// 渲染展开收起按钮的隐藏占位元素
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user