Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in / Register
Toggle navigation
R
relation-graph
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
郭铭瑶
relation-graph
Commits
4ee6c475
Commit
4ee6c475
authored
Aug 16, 2021
by
郭铭瑶
🤘
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
调整
parent
674f4769
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
108 additions
and
299 deletions
+108
-299
api.js
src/ajax/api.js
+1
-0
main.vue
src/components/main.vue
+27
-31
useD3.js
src/util/useD3.js
+80
-268
No files found.
src/ajax/api.js
View file @
4ee6c475
...
@@ -14,4 +14,5 @@ export default {
...
@@ -14,4 +14,5 @@ export default {
DELETE_RELATION
:
'/node/relation'
,
DELETE_RELATION
:
'/node/relation'
,
GET_NODES
:
'/node/relations'
,
GET_NODES
:
'/node/relations'
,
DELETE_NODE
:
'/node/{id}'
,
DELETE_NODE
:
'/node/{id}'
,
GET_SYSTEMS
:
'/systems'
,
}
}
src/components/main.vue
View file @
4ee6c475
...
@@ -103,19 +103,6 @@ export default {
...
@@ -103,19 +103,6 @@ export default {
const
graphData
=
ref
({
nodes
:
[],
links
:
[]
})
const
graphData
=
ref
({
nodes
:
[],
links
:
[]
})
const
subjectNodes
=
ref
([])
const
subjectNodes
=
ref
([])
function
fetchSubjects
()
{
function
fetchSubjects
()
{
// ajax
// .get({
// url: api.GET_NODES,
// params: { nodeId: '572563400077869056' },
// })
// .then((res) => {
// console.log('nodes:', res)
// graphData.value = res.data.content
// systemOptions.value = graphData.value.nodes
// .filter((node) => node.nodeLabel === 'System')
// .map((node) => ({ label: node.systemName, value: node.nodeId }))
// })
ajax
ajax
.
get
({
.
get
({
url
:
api
.
GET_SUBJECTS
,
url
:
api
.
GET_SUBJECTS
,
...
@@ -138,14 +125,28 @@ export default {
...
@@ -138,14 +125,28 @@ export default {
if
(
!
res
.
data
||
!
res
.
data
.
content
)
return
if
(
!
res
.
data
||
!
res
.
data
.
content
)
return
relationOptions
.
value
=
res
.
data
.
content
.
map
((
item
)
=>
({
relationOptions
.
value
=
res
.
data
.
content
.
map
((
item
)
=>
({
label
:
item
.
relationName
,
label
:
item
.
relationName
,
value
:
item
.
id
,
value
:
item
.
id
+
''
,
}))
})
ajax
.
get
({
url
:
api
.
GET_SYSTEMS
,
})
.
then
((
res
)
=>
{
if
(
!
res
.
data
||
!
res
.
data
.
content
)
return
systemOptions
.
value
=
res
.
data
.
content
.
map
((
item
)
=>
({
label
:
item
.
systemName
,
value
:
item
.
id
+
''
,
}))
}))
})
})
function
fetchSubordinates
(
params
=
null
)
{
function
fetchSubordinates
(
params
=
null
)
{
ajax
ajax
.
get
({
.
get
({
url
:
api
.
GET_NODES
,
url
:
api
.
GET_NODES
,
params
,
params
:
{
type
:
params
.
nodeLabel
,
nodeId
:
params
.
nodeId
,
},
})
})
.
then
((
res
)
=>
{
.
then
((
res
)
=>
{
const
{
links
,
nodes
}
=
res
.
data
.
content
const
{
links
,
nodes
}
=
res
.
data
.
content
...
@@ -166,9 +167,6 @@ export default {
...
@@ -166,9 +167,6 @@ export default {
),
),
],
],
}
}
systemOptions
.
value
=
graphData
.
value
.
nodes
.
filter
((
node
)
=>
node
.
nodeLabel
===
'System'
)
.
map
((
node
)
=>
({
label
:
node
.
systemName
,
value
:
node
.
nodeId
}))
})
})
}
}
function
handleAdd
({
nodeId
})
{
function
handleAdd
({
nodeId
})
{
...
@@ -197,7 +195,10 @@ export default {
...
@@ -197,7 +195,10 @@ export default {
},
},
})
})
.
then
(()
=>
{
.
then
(()
=>
{
fetchSubordinates
({
nodeId
:
subjectId
.
value
})
fetchSubordinates
({
nodeId
:
subjectId
.
value
,
nodeLabel
:
'Subject'
,
})
isLoading
.
value
=
false
isLoading
.
value
=
false
showDrawer
.
value
=
false
showDrawer
.
value
=
false
message
.
success
(
'提交成功'
)
message
.
success
(
'提交成功'
)
...
@@ -224,7 +225,6 @@ export default {
...
@@ -224,7 +225,6 @@ export default {
if
(
data
.
nodeLabel
===
'Subject'
)
{
if
(
data
.
nodeLabel
===
'Subject'
)
{
fetchSubjects
()
fetchSubjects
()
}
else
{
}
else
{
// fetchSubordinates({ nodeId: data.subjectId })
graphData
.
value
=
{
graphData
.
value
=
{
nodes
:
graphData
.
value
.
nodes
.
filter
(
nodes
:
graphData
.
value
.
nodes
.
filter
(
(
node
)
=>
node
.
id
!=
data
.
id
(
node
)
=>
node
.
id
!=
data
.
id
...
@@ -264,7 +264,6 @@ export default {
...
@@ -264,7 +264,6 @@ export default {
})
})
}
}
const
handleSearch
=
(
key
)
=>
{
const
handleSearch
=
(
key
)
=>
{
console
.
log
(
key
)
if
(
!
key
)
{
if
(
!
key
)
{
fetchSubjects
()
fetchSubjects
()
return
return
...
@@ -276,9 +275,6 @@ export default {
...
@@ -276,9 +275,6 @@ export default {
})
})
.
then
((
res
)
=>
{
.
then
((
res
)
=>
{
graphData
.
value
=
res
.
data
.
content
graphData
.
value
=
res
.
data
.
content
systemOptions
.
value
=
graphData
.
value
.
nodes
.
filter
((
node
)
=>
node
.
nodeLabel
===
'System'
)
.
map
((
node
)
=>
({
label
:
node
.
systemName
,
value
:
node
.
nodeId
}))
})
})
}
}
return
{
return
{
...
@@ -317,13 +313,13 @@ export default {
...
@@ -317,13 +313,13 @@ export default {
trigger
:
[
'input'
,
'blur'
],
trigger
:
[
'input'
,
'blur'
],
},
},
],
],
//
systemId: [
systemId
:
[
//
{
{
//
required: true,
required
:
true
,
//
message: '请选择所属系统',
message
:
'请选择所属系统'
,
//
trigger: ['input', 'blur'],
trigger
:
[
'input'
,
'blur'
],
//
},
},
//
],
],
},
},
curNode
,
curNode
,
handleDelete
,
handleDelete
,
...
...
src/util/useD3.js
View file @
4ee6c475
...
@@ -79,7 +79,7 @@ const defaultConfig = {
...
@@ -79,7 +79,7 @@ const defaultConfig = {
isScale
:
true
,
// 是否启用缩放平移zoom功能
isScale
:
true
,
// 是否启用缩放平移zoom功能
scaleExtent
:
[
0.2
,
1.5
],
// 缩放的比例尺
scaleExtent
:
[
0.2
,
1.5
],
// 缩放的比例尺
chargeStrength
:
-
100
,
// 万有引力
chargeStrength
:
-
100
,
// 万有引力
collide
:
10
0
,
// 碰撞力的大小 (节点之间的间距)
collide
:
9
0
,
// 碰撞力的大小 (节点之间的间距)
alphaDecay
:
0.0228
,
// 控制力学模拟衰减率
alphaDecay
:
0.0228
,
// 控制力学模拟衰减率
r
:
45
,
// 圈圈的半径 [30 - 45]
r
:
45
,
// 圈圈的半径 [30 - 45]
nodeColor
:
'skyblue'
,
// 圈圈节点背景颜色
nodeColor
:
'skyblue'
,
// 圈圈节点背景颜色
...
@@ -116,24 +116,11 @@ export default class RelationGraph {
...
@@ -116,24 +116,11 @@ export default class RelationGraph {
// 画布
// 画布
this
.
graph
=
d3
.
select
(
selector
)
this
.
graph
=
d3
.
select
(
selector
)
// 转换links的source和target
const
nodes
=
[...
data
.
nodes
]
const
links
=
[...
data
.
links
]
links
.
forEach
((
link
)
=>
{
nodes
.
forEach
((
node
)
=>
{
if
(
node
.
id
===
link
.
source
)
{
link
.
source
=
node
}
else
if
(
node
.
id
===
link
.
target
)
{
link
.
target
=
node
}
})
})
// 合并配置
// 合并配置
this
.
config
=
Object
.
assign
(
this
.
config
=
Object
.
assign
(
{},
{},
defaultConfig
,
defaultConfig
,
{
links
,
nodes
}
,
this
.
transformData
(
data
)
,
{
{
width
:
mapW
,
width
:
mapW
,
height
:
mapH
,
height
:
mapH
,
...
@@ -145,21 +132,11 @@ export default class RelationGraph {
...
@@ -145,21 +132,11 @@ export default class RelationGraph {
this
.
dependsNode
=
[]
this
.
dependsNode
=
[]
this
.
dependsLinkAndText
=
[]
this
.
dependsLinkAndText
=
[]
// console.log('init', this.config)
this
.
createSimulation
()
this
.
init
()
this
.
init
()
}
}
setKey
(
key
)
{
d3
.
selectAll
(
'.node-text'
)
.
text
((
d
)
=>
(
key
&&
d
[
key
])
||
'无'
)
// .text((d) => (key && d[key]) || d[d.nodeLabel.toLowerCase() + 'Name'])
.
call
(
textWrap
,
this
.
config
.
r
*
1.8
)
}
update
(
data
)
{
const
self
=
this
const
t
=
d3
.
transition
().
duration
(
750
)
// 转换links的source和target
// 转换links的source和target
transformData
(
data
)
{
const
nodes
=
[...
data
.
nodes
]
const
nodes
=
[...
data
.
nodes
]
const
links
=
[...
data
.
links
]
const
links
=
[...
data
.
links
]
links
.
forEach
((
link
)
=>
{
links
.
forEach
((
link
)
=>
{
...
@@ -171,14 +148,20 @@ export default class RelationGraph {
...
@@ -171,14 +148,20 @@ export default class RelationGraph {
}
}
})
})
})
})
this
.
config
.
nodes
=
[...
nodes
]
return
{
links
,
nodes
}
this
.
config
.
links
=
[...
links
]
}
console
.
log
(
'update'
,
this
.
config
)
// d3.selectAll('pattern.circle-bg').data(this.config.nodes)
setKey
(
key
)
{
// d3.selectAll('g.circle-wrapper').data(this.config.nodes)
d3
.
selectAll
(
'.node-text'
)
// d3.selectAll('g.edge').data(this.config.links)
.
text
((
d
)
=>
(
key
&&
d
[
key
])
||
'无'
)
// .text((d) => (key && d[key]) || d[d.nodeLabel.toLowerCase() + 'Name'])
.
call
(
textWrap
,
this
.
config
.
r
*
1.8
)
}
initPatterns
()
{
this
.
patterns
&&
this
.
patterns
.
remove
()
this
.
patterns
.
remove
()
// 3.2 添加多个圈圈图片的 <pattern>
this
.
patterns
=
this
.
defs
this
.
patterns
=
this
.
defs
.
selectAll
(
'pattern.circle-bg'
)
.
selectAll
(
'pattern.circle-bg'
)
.
data
(
this
.
config
.
nodes
)
.
data
(
this
.
config
.
nodes
)
...
@@ -210,17 +193,19 @@ export default class RelationGraph {
...
@@ -210,17 +193,19 @@ export default class RelationGraph {
.
attr
(
'fill'
,
this
.
config
.
fontColor
)
.
attr
(
'fill'
,
this
.
config
.
fontColor
)
.
style
(
'font-size'
,
this
.
config
.
r
/
3.8
)
.
style
(
'font-size'
,
this
.
config
.
r
/
3.8
)
.
text
((
d
)
=>
d
[
d
.
nodeLabel
.
toLowerCase
()
+
'Name'
])
.
text
((
d
)
=>
d
[
d
.
nodeLabel
.
toLowerCase
()
+
'Name'
])
}
initLinks
()
{
const
self
=
this
this
.
edges
&&
this
.
edges
.
remove
()
// 5.关系图添加线
// 5.关系图添加线
// 5.1 每条线是个容器,有线 和一个装文字的容器
// 5.1 每条线是个容器,有线 和一个装文字的容器
this
.
edges
.
remove
()
this
.
edges
=
this
.
relMap_g
this
.
edges
=
this
.
relMap_g
.
selectAll
(
'g.edge'
)
.
selectAll
(
'g.edge'
)
.
data
(
this
.
config
.
links
)
.
data
(
this
.
config
.
links
)
.
enter
()
.
enter
()
.
append
(
'g'
)
.
append
(
'g'
)
.
attr
(
'class'
,
'edge'
)
.
attr
(
'class'
,
'edge'
)
.
merge
(
this
.
edges
)
.
on
(
'mouseover'
,
function
(
e
,
d
)
{
.
on
(
'mouseover'
,
function
(
e
,
d
)
{
if
(
self
.
config
.
isHighLight
)
{
if
(
self
.
config
.
isHighLight
)
{
self
.
highlightLinks
(
d
)
self
.
highlightLinks
(
d
)
...
@@ -272,16 +257,20 @@ export default class RelationGraph {
...
@@ -272,16 +257,20 @@ export default class RelationGraph {
.
attr
(
'text-anchor'
,
'middle'
)
// <text>文本中轴对齐方式居中 start | middle | end
.
attr
(
'text-anchor'
,
'middle'
)
// <text>文本中轴对齐方式居中 start | middle | end
.
style
(
'font-size'
,
12
)
.
style
(
'font-size'
,
12
)
.
text
((
d
)
=>
d
.
name
)
.
text
((
d
)
=>
d
.
name
)
}
initCircles
()
{
const
self
=
this
this
.
circlesWrapper
&&
this
.
circlesWrapper
.
remove
()
// 给圈圈节点添加g便于后面添加menu
// 给圈圈节点添加g便于后面添加menu
this
.
circlesWrapper
.
remove
()
this
.
circlesWrapper
=
this
.
relMap_g
this
.
circlesWrapper
=
this
.
relMap_g
.
selectAll
(
'g.circle-wrapper'
)
.
selectAll
(
'g.circle-wrapper'
)
.
data
(
this
.
config
.
nodes
)
.
data
(
this
.
config
.
nodes
)
.
enter
()
.
enter
()
.
append
(
'g'
)
.
append
(
'g'
)
.
attr
(
'class'
,
'circle-wrapper'
)
.
attr
(
'class'
,
'circle-wrapper'
)
.
merge
(
this
.
circlesWrapper
)
//
.merge(this.circlesWrapper)
this
.
circlesWrapper
.
exit
().
remove
()
this
.
circlesWrapper
.
exit
().
remove
()
// 6.关系图添加用于显示圈圈的节点
// 6.关系图添加用于显示圈圈的节点
...
@@ -303,11 +292,6 @@ export default class RelationGraph {
...
@@ -303,11 +292,6 @@ export default class RelationGraph {
if
(
self
.
config
.
isHighLight
)
{
if
(
self
.
config
.
isHighLight
)
{
self
.
highlightObject
(
d
)
self
.
highlightObject
(
d
)
}
}
// tooltip
// .html(d.name)
// .style('left', e.pageX + 10 + 'px')
// .style('top', e.pageY + 10 + 'px')
// .style('opacity', 1)
})
})
.
on
(
'mouseout'
,
function
(
e
,
d
)
{
.
on
(
'mouseout'
,
function
(
e
,
d
)
{
d3
.
select
(
this
).
attr
(
'stroke-width'
,
self
.
config
.
strokeWidth
)
d3
.
select
(
this
).
attr
(
'stroke-width'
,
self
.
config
.
strokeWidth
)
...
@@ -315,7 +299,6 @@ export default class RelationGraph {
...
@@ -315,7 +299,6 @@ export default class RelationGraph {
if
(
self
.
config
.
isHighLight
)
{
if
(
self
.
config
.
isHighLight
)
{
self
.
highlightObject
(
null
)
self
.
highlightObject
(
null
)
}
}
// tooltip.style('opacity', 0)
})
})
.
on
(
'click'
,
function
(
e
,
d
)
{
.
on
(
'click'
,
function
(
e
,
d
)
{
if
(
menu
&&
menu
.
curNodeData
==
d
)
{
if
(
menu
&&
menu
.
curNodeData
==
d
)
{
...
@@ -325,7 +308,7 @@ export default class RelationGraph {
...
@@ -325,7 +308,7 @@ export default class RelationGraph {
if
(
d
.
nodeLabel
===
'Subject'
)
{
if
(
d
.
nodeLabel
===
'Subject'
)
{
self
.
openMenu
(
this
,
d
)
self
.
openMenu
(
this
,
d
)
}
else
{
}
else
{
self
.
openMenu
(
this
,
d
,
'del'
)
self
.
openMenu
(
this
,
d
,
[
'del'
,
'branch'
]
)
}
}
}
}
//阻止事件冒泡 阻止事件默认行为
//阻止事件冒泡 阻止事件默认行为
...
@@ -368,9 +351,13 @@ export default class RelationGraph {
...
@@ -368,9 +351,13 @@ export default class RelationGraph {
// 文字折行
// 文字折行
this
.
SVG
.
selectAll
(
'text.node-text'
).
call
(
textWrap
,
this
.
config
.
r
*
1.8
)
this
.
SVG
.
selectAll
(
'text.node-text'
).
call
(
textWrap
,
this
.
config
.
r
*
1.8
)
}
this
.
simulation
// 创建力学模拟器
.
nodes
(
this
.
config
.
nodes
)
initSimulation
()
{
// 1. 创建一个力学模拟器
this
.
simulation
=
d3
.
forceSimulation
(
this
.
config
.
nodes
)
// simulation.force(name,[force])函数,添加某种力
// simulation.force(name,[force])函数,添加某种力
.
force
(
'link'
,
d3
.
forceLink
(
this
.
config
.
links
))
.
force
(
'link'
,
d3
.
forceLink
(
this
.
config
.
links
))
// 万有引力
// 万有引力
...
@@ -391,25 +378,58 @@ export default class RelationGraph {
...
@@ -391,25 +378,58 @@ export default class RelationGraph {
.
alphaDecay
(
this
.
config
.
alphaDecay
)
.
alphaDecay
(
this
.
config
.
alphaDecay
)
// 监听事件 ,tick|end ,例如监听 tick 滴答事件
// 监听事件 ,tick|end ,例如监听 tick 滴答事件
.
on
(
'tick'
,
()
=>
this
.
ticked
())
.
on
(
'tick'
,
()
=>
this
.
ticked
())
}
this
.
simulation
.
alphaTarget
(
0.3
).
restart
()
update
(
data
)
{
const
{
nodes
,
links
}
=
this
.
transformData
(
data
)
this
.
config
.
nodes
=
[...
nodes
]
this
.
config
.
links
=
[...
links
]
console
.
log
(
'update'
,
this
.
config
)
this
.
initPatterns
()
this
.
initLinks
()
this
.
initCircles
()
// this.initSimulation()
// // 1. 创建一个力学模拟器
this
.
simulation
.
nodes
(
this
.
config
.
nodes
)
.
force
(
'link'
,
d3
.
forceLink
(
this
.
config
.
links
))
// .force('charge', d3.forceManyBody().strength(this.config.chargeStrength))
// .force(
// 'center',
// d3.forceCenter(this.config.width / 2, this.config.height / 2)
// )
// // .force(
// // 'collide',
// // d3.forceCollide(this.config.collide).strength(0.2).iterations(5)
// // )
// // .alphaDecay(this.config.alphaDecay)
// // .on('tick', () => this.ticked())
this
.
simulation
.
alphaTarget
(
0.1
).
restart
()
const
timer
=
setTimeout
(()
=>
{
const
timer
=
setTimeout
(()
=>
{
this
.
simulation
.
alphaTarget
(
0
)
this
.
simulation
.
alphaTarget
(
0
)
clearTimeout
(
timer
)
clearTimeout
(
timer
)
},
500
)
},
500
)
}
}
openMenu
(
self
,
d
,
type
)
{
openMenu
(
self
,
d
,
types
)
{
this
.
setCurNode
(
d
)
this
.
setCurNode
(
d
)
menu
=
new
RadialMenu
().
radius
(
50
).
thickness
(
40
).
appendTo
(
self
.
parentNode
)
menu
=
new
RadialMenu
().
radius
(
50
).
thickness
(
40
).
appendTo
(
self
.
parentNode
)
if
(
!
type
)
{
if
(
!
type
s
)
{
menu
.
show
(
this
.
menuData
,
d
)
menu
.
show
(
this
.
menuData
,
d
)
}
else
{
}
else
{
menu
.
show
(
menu
.
show
(
this
.
menuData
.
filter
((
e
)
=>
e
.
key
===
type
),
this
.
menuData
.
filter
((
e
)
=>
types
.
indexOf
(
e
.
key
)
>=
0
),
d
d
)
)
}
}
}
}
closeMenu
()
{
closeMenu
()
{
if
(
menu
)
{
if
(
menu
)
{
menu
.
hide
()
menu
.
hide
()
...
@@ -417,38 +437,7 @@ export default class RelationGraph {
...
@@ -417,38 +437,7 @@ export default class RelationGraph {
}
}
}
}
// 创建力学模拟器
createSimulation
()
{
// 1. 创建一个力学模拟器
this
.
simulation
=
d3
.
forceSimulation
(
this
.
config
.
nodes
)
// simulation.force(name,[force])函数,添加某种力
.
force
(
'link'
,
d3
.
forceLink
(
this
.
config
.
links
))
// 万有引力
.
force
(
'charge'
,
d3
.
forceManyBody
().
strength
(
this
.
config
.
chargeStrength
))
// d3.forceCenter()用指定的x坐标和y坐标创建一个新的居中力。
.
force
(
'center'
,
d3
.
forceCenter
(
this
.
config
.
width
/
2
,
this
.
config
.
height
/
2
)
)
// 碰撞作用力,为节点指定一个radius区域来防止节点重叠,设置碰撞力的强度,范围[0,1], 默认为0.7。
// 设置迭代次数,默认为1,迭代次数越多最终的布局效果越好,但是计算复杂度更高
.
force
(
'collide'
,
d3
.
forceCollide
(
this
.
config
.
collide
).
strength
(
0.2
).
iterations
(
5
)
)
// 在计时器的每一帧中,仿真的alpha系数会不断削减,当alpha到达一个系数时,仿真将会停止,也就是alpha的目标系数alphaTarget,该值区间为[0,1]. 默认为0,
// 控制力学模拟衰减率,[0-1] ,设为0则不停止 , 默认0.0228,直到0.001
.
alphaDecay
(
this
.
config
.
alphaDecay
)
// 监听事件 ,tick|end ,例如监听 tick 滴答事件
.
on
(
'tick'
,
()
=>
this
.
ticked
())
}
init
()
{
init
()
{
const
self
=
this
// this.createSimulation()
// 2.创建svg标签
// 2.创建svg标签
this
.
SVG
=
this
.
graph
this
.
SVG
=
this
.
graph
.
append
(
'svg'
)
.
append
(
'svg'
)
...
@@ -486,202 +475,25 @@ export default class RelationGraph {
...
@@ -486,202 +475,25 @@ export default class RelationGraph {
.
attr
(
'd'
,
'M 0 0 8 4 0 8Z'
)
//箭头的路径 从 (0,0) 到 (8,4) 到(0,8)
.
attr
(
'd'
,
'M 0 0 8 4 0 8Z'
)
//箭头的路径 从 (0,0) 到 (8,4) 到(0,8)
.
attr
(
'fill'
,
this
.
config
.
linkColor
)
.
attr
(
'fill'
,
this
.
config
.
linkColor
)
// 3.2 添加多个圈圈图片的 <pattern>
this
.
initSimulation
()
this
.
patterns
=
this
.
defs
.
selectAll
(
'pattern.circle-bg'
)
.
data
(
this
.
config
.
nodes
)
.
enter
()
.
append
(
'pattern'
)
.
attr
(
'class'
,
'circle-bg'
)
.
attr
(
'id'
,
(
d
)
=>
d
.
id
)
.
attr
(
'width'
,
'1'
)
.
attr
(
'height'
,
'1'
)
this
.
patterns
.
append
(
'rect'
)
.
attr
(
'width'
,
2
*
this
.
config
.
r
)
.
attr
(
'height'
,
2
*
this
.
config
.
r
)
.
attr
(
'fill'
,
(
d
)
=>
(
d
&&
this
.
config
.
colorList
[
d
.
nodeLabel
||
'default'
])
||
this
.
config
.
nodeColor
)
this
.
patterns
this
.
initPatterns
()
.
append
(
'text'
)
.
attr
(
'class'
,
'node-text'
)
.
attr
(
'x'
,
this
.
config
.
r
)
.
attr
(
'y'
,
this
.
config
.
r
)
// edit
.
attr
(
'text-anchor'
,
'middle'
)
.
attr
(
'dominant-baseline'
,
'middle'
)
.
attr
(
'fill'
,
this
.
config
.
fontColor
)
.
style
(
'font-size'
,
this
.
config
.
r
/
3.8
)
.
text
((
d
)
=>
d
[
d
.
nodeLabel
.
toLowerCase
()
+
'Name'
])
// 4.放关系图的容器
// 4.放关系图的容器
this
.
relMap_g
=
this
.
SVG
.
append
(
'g'
)
this
.
relMap_g
=
this
.
SVG
.
append
(
'g'
)
.
attr
(
'class'
,
'relMap_g'
)
.
attr
(
'class'
,
'relMap_g'
)
.
attr
(
'width'
,
this
.
config
.
width
)
.
attr
(
'width'
,
this
.
config
.
width
)
.
attr
(
'height'
,
this
.
config
.
height
)
.
attr
(
'height'
,
this
.
config
.
height
)
// 5.关系图添加线
// 5.1 每条线是个容器,有线 和一个装文字的容器
this
.
edges
=
this
.
relMap_g
.
selectAll
(
'g.edge'
)
.
data
(
this
.
config
.
links
)
.
enter
()
.
append
(
'g'
)
.
attr
(
'class'
,
'edge'
)
.
on
(
'mouseover'
,
function
(
e
,
d
)
{
if
(
self
.
config
.
isHighLight
)
{
self
.
highlightLinks
(
d
)
}
d3
.
select
(
this
).
selectAll
(
'path.links'
).
attr
(
'stroke-width'
,
2
)
d3
.
select
(
this
).
selectAll
(
'.rect_g text'
).
style
(
'font-weight'
,
'bold'
)
})
.
on
(
'mouseout'
,
function
()
{
if
(
self
.
config
.
isHighLight
)
{
self
.
highlightLinks
(
null
)
}
d3
.
select
(
this
).
selectAll
(
'path.links'
).
attr
(
'stroke-width'
,
1
)
d3
.
select
(
this
).
selectAll
(
'.rect_g text'
).
style
(
'font-weight'
,
'normal'
)
})
.
on
(
'click'
,
function
(
e
,
d
)
{
console
.
log
(
'线click'
)
})
.
attr
(
'fill'
,
(
d
)
=>
d
.
color
||
this
.
config
.
linkColor
)
// 5.2 添加线
this
.
links
=
this
.
edges
.
append
(
'path'
)
.
attr
(
'class'
,
'links'
)
.
attr
(
'd'
,
(
d
)
=>
`M
${
this
.
config
.
linkSrc
}
,0 L
${
getDis
(
d
.
source
,
d
.
target
)}
,0`
)
.
style
(
'marker-end'
,
'url(#marker)'
)
.
attr
(
'stroke'
,
(
d
)
=>
d
.
color
||
this
.
config
.
linkColor
)
// 5.3 添加关系文字的容器
this
.
rect_g
=
this
.
edges
.
append
(
'g'
).
attr
(
'class'
,
'rect_g'
)
// 5.4 添加rect
this
.
rects
=
this
.
rect_g
.
append
(
'rect'
)
.
attr
(
'x'
,
40
)
.
attr
(
'y'
,
-
10
)
.
attr
(
'width'
,
50
)
.
attr
(
'height'
,
20
)
.
attr
(
'fill'
,
'#f9fbfd'
)
.
attr
(
'stroke'
,
'transparent'
)
// 5.5 文本标签 坐标(x,y)代表 文本的左下角的点
this
.
initLinks
()
this
.
texts
=
this
.
rect_g
.
append
(
'text'
)
.
attr
(
'x'
,
40
)
.
attr
(
'y'
,
5
)
.
attr
(
'text-anchor'
,
'middle'
)
// <text>文本中轴对齐方式居中 start | middle | end
.
style
(
'font-size'
,
12
)
.
text
((
d
)
=>
d
.
name
)
const
tooltip
=
d3
.
select
(
'body'
)
.
append
(
'div'
)
.
attr
(
'class'
,
'relation-tooltip'
)
.
style
(
'opacity'
,
0
)
// 给圈圈节点添加g便于后面添加menu
// const tooltip = d3
this
.
circlesWrapper
=
this
.
relMap_g
// .select('body')
.
selectAll
(
'g.circle-wrapper'
)
// .append('div')
.
data
(
this
.
config
.
nodes
)
// .attr('class', 'relation-tooltip')
.
enter
()
// .style('opacity', 0)
.
append
(
'g'
)
.
attr
(
'class'
,
'circle-wrapper'
)
// 6.关系图添加用于显示圈圈的节点
this
.
circles
=
this
.
circlesWrapper
.
append
(
'circle'
)
.
attr
(
'r'
,
this
.
config
.
r
)
.
attr
(
'class'
,
'node'
)
.
style
(
'cursor'
,
'pointer'
)
.
attr
(
'fill'
,
(
d
)
=>
`url(#
${
d
.
id
}
)`
)
.
attr
(
'stroke'
,
this
.
config
.
strokeColor
)
.
attr
(
'stroke-width'
,
this
.
config
.
strokeWidth
)
.
on
(
'mouseover'
,
function
(
e
,
d
)
{
d3
.
select
(
this
).
attr
(
'stroke-width'
,
self
.
config
.
strokeWidth
==
0
?
3
:
1.5
*
self
.
config
.
strokeWidth
)
d3
.
select
(
this
).
attr
(
'stroke'
,
'rgba(0,0,0,0.1)'
)
// d3.select(this).attr('stroke', d.strokeColor || self.config.strokeColor)
if
(
self
.
config
.
isHighLight
)
{
self
.
highlightObject
(
d
)
}
// tooltip
// .html(d.name)
// .style('left', e.pageX + 10 + 'px')
// .style('top', e.pageY + 10 + 'px')
// .style('opacity', 1)
})
.
on
(
'mouseout'
,
function
(
e
,
d
)
{
d3
.
select
(
this
).
attr
(
'stroke-width'
,
self
.
config
.
strokeWidth
)
d3
.
select
(
this
).
attr
(
'stroke'
,
d
.
strokeColor
||
self
.
config
.
strokeColor
)
if
(
self
.
config
.
isHighLight
)
{
self
.
highlightObject
(
null
)
}
// tooltip.style('opacity', 0)
})
.
on
(
'click'
,
function
(
e
,
d
)
{
if
(
menu
&&
menu
.
curNodeData
==
d
)
{
self
.
closeMenu
()
}
else
{
self
.
closeMenu
()
if
(
d
.
nodeLabel
===
'Subject'
)
{
self
.
openMenu
(
this
,
d
)
}
else
{
self
.
openMenu
(
this
,
d
,
'del'
)
}
}
//阻止事件冒泡 阻止事件默认行为
e
.
stopPropagation
?
e
.
stopPropagation
()
:
(
e
.
cancelBubble
=
true
)
e
.
preventDefault
?
e
.
preventDefault
()
:
(
e
.
returnValue
=
false
)
})
.
on
(
'contextmenu'
,
function
(
e
)
{
// 取消鼠标右键菜单默认行为
e
.
cancelBubble
=
true
e
.
returnValue
=
false
})
// 应用 自定义的 拖拽事件
.
call
(
d3
.
drag
()
.
on
(
'start'
,
(
e
,
d
)
=>
{
e
.
sourceEvent
.
stopPropagation
()
// restart()方法重新启动模拟器的内部计时器并返回模拟器。
// 与simulation.alphaTarget或simulation.alpha一起使用时,此方法可用于在交互
// 过程中进行“重新加热”模拟,例如在拖动节点时,在simulation.stop暂停之后恢复模拟。
// 当前alpha值为0,需设置alphaTarget让节点动起来
if
(
!
e
.
active
)
this
.
simulation
.
alphaTarget
(
0.3
).
restart
()
d
.
fx
=
d
.
x
d
.
fy
=
d
.
y
})
.
on
(
'drag'
,
(
e
,
d
)
=>
{
// d.fx属性- 节点的固定x位置
// 在每次tick结束时,d.x被重置为d.fx ,并将节点 d.vx设置为零
// 要取消节点,请将节点 .fx和节点 .fy设置为空,或删除这些属性。
d
.
fx
=
e
.
x
d
.
fy
=
e
.
y
})
.
on
(
'end'
,
(
e
,
d
)
=>
{
// 让alpha目标值值恢复为默认值0,停止力模型
if
(
!
e
.
active
)
this
.
simulation
.
alphaTarget
(
0
)
d
.
fx
=
null
d
.
fy
=
null
})
)
// 文字折行
this
.
initCircles
()
this
.
SVG
.
selectAll
(
'text.node-text'
).
call
(
textWrap
,
this
.
config
.
r
*
1.8
)
}
}
ticked
()
{
ticked
()
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment