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
bcfd01c7
Commit
bcfd01c7
authored
Aug 14, 2021
by
郭铭瑶
🤘
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
节点添加及删除操作
parent
57460837
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
385 additions
and
47 deletions
+385
-47
api.js
src/ajax/api.js
+1
-0
d3.vue
src/components/d3.vue
+12
-0
footer.vue
src/components/footer.vue
+7
-2
main.vue
src/components/main.vue
+139
-26
nav.vue
src/components/nav.vue
+19
-3
useD3.js
src/util/useD3.js
+207
-16
No files found.
src/ajax/api.js
View file @
bcfd01c7
...
@@ -7,6 +7,7 @@ switch (process.env.NODE_ENV) {
...
@@ -7,6 +7,7 @@ switch (process.env.NODE_ENV) {
export
default
{
export
default
{
BASE_URL
,
BASE_URL
,
GET_SUBJECTS
:
'/subjects'
,
GET_RELATIONS
:
'/relations'
,
GET_RELATIONS
:
'/relations'
,
POST_SUBJECT
:
'/subject'
,
POST_SUBJECT
:
'/subject'
,
POST_NODE
:
'/node/relation'
,
POST_NODE
:
'/node/relation'
,
...
...
src/components/d3.vue
View file @
bcfd01c7
...
@@ -100,6 +100,18 @@ export default {
...
@@ -100,6 +100,18 @@ export default {
colorList
,
colorList
,
setCurNode
setCurNode
)
)
// if (instance)
{
// instance.update(props.data)
//
}
else
{
// instance = new RelationGraph(
// container.value,
// props.data,
// props.config,
// menuData,
// colorList,
// setCurNode
// )
//
}
setLegend
()
setLegend
()
}
}
function
setKey
(
key
)
{
function
setKey
(
key
)
{
...
...
src/components/footer.vue
View file @
bcfd01c7
<
template
>
<
template
>
<div
class=
"footer"
>
<div
class=
"footer"
>
<n-button
type=
"primary"
ghost
@
click=
"addSubject"
>
Add Subject
</n-button>
<n-space>
<n-space>
<n-tag
v-show=
"nodeVal"
size=
"small"
round
:color=
"color"
>
<n-tag
v-show=
"nodeVal"
size=
"small"
round
:color=
"color"
>
{{
nodeVal
&&
nodeVal
.
nodeLabel
}}
{{
nodeVal
&&
nodeVal
.
nodeLabel
}}
...
@@ -31,7 +32,7 @@ export default defineComponent({
...
@@ -31,7 +32,7 @@ export default defineComponent({
}),
}),
},
},
},
},
emits
:
[
'set'
],
emits
:
[
'set'
,
'add'
],
setup
(
props
,
ctx
)
{
setup
(
props
,
ctx
)
{
const
colorList
=
{
const
colorList
=
{
default
:
'skyblue'
,
default
:
'skyblue'
,
...
@@ -65,12 +66,16 @@ export default defineComponent({
...
@@ -65,12 +66,16 @@ export default defineComponent({
'nodeId'
,
'nodeId'
,
'nodeLabel'
,
'nodeLabel'
,
])
])
const
addSubject
=
()
=>
{
ctx
.
emit
(
'add'
)
}
return
{
return
{
curKey
,
curKey
,
setKey
,
setKey
,
list
,
list
,
color
,
color
,
nodeVal
,
nodeVal
,
addSubject
,
}
}
},
},
})
})
...
@@ -80,7 +85,7 @@ export default defineComponent({
...
@@ -80,7 +85,7 @@ export default defineComponent({
.footer
.footer
display flex
display flex
align-items center
align-items center
justify-content
flex-end
justify-content
space-between
padding 0 15px 8px
padding 0 15px 8px
background #f8f9fb
background #f8f9fb
box-shadow 10px 6px 10px 0 #000
box-shadow 10px 6px 10px 0 #000
...
...
src/components/main.vue
View file @
bcfd01c7
<
template
>
<
template
>
<div
class=
"main"
>
<div
class=
"main"
>
<Nav
style=
"grid-area: nav"
/>
<Nav
style=
"grid-area: nav"
@
search=
"handleSearch"
/>
<D3
<D3
ref=
"d3Ref"
ref=
"d3Ref"
style=
"grid-area: content"
style=
"grid-area: content"
class=
"graph"
class=
"graph"
:data=
"data"
:data=
"data"
@
branch=
"
handleBranch
"
@
branch=
"
fetchSubordinates
"
@
add=
"handleAdd"
@
add=
"handleAdd"
@
curNode=
"curNode = $event"
@
curNode=
"curNode = $event"
@
del=
"handleDelete"
@
del=
"handleDelete"
/>
/>
<Side
style=
"grid-area: side"
/>
<Side
style=
"grid-area: side"
/>
<Footer
style=
"grid-area: footer"
:node=
"curNode"
@
set=
"setKey"
/>
<Footer
style=
"grid-area: footer"
:node=
"curNode"
@
add=
"showSubjectDrawer = true"
@
set=
"setKey"
/>
</div>
</div>
<n-drawer
v-model:show=
"showDrawer"
:width=
"400"
placement=
"left"
>
<n-drawer
v-model:show=
"showDrawer"
:width=
"400"
placement=
"left"
>
<n-drawer-content
title=
"新增节点"
>
<n-drawer-content
title=
"新增节点"
>
...
@@ -46,6 +51,24 @@
...
@@ -46,6 +51,24 @@
</n-form>
</n-form>
</n-drawer-content>
</n-drawer-content>
</n-drawer>
</n-drawer>
<n-drawer
v-model:show=
"showSubjectDrawer"
:width=
"400"
placement=
"left"
>
<n-drawer-content
title=
"新增Suject"
>
<n-form
ref=
"subjectFormRef"
:model=
"subjectData"
:rules=
"rules"
>
<n-form-item
path=
"subjectName"
label=
"名称"
>
<n-input
v-model:value=
"subjectData.subjectName"
placeholder=
"请输入"
@
keydown
.
enter
.
prevent
/>
</n-form-item>
<n-space
justify=
"end"
>
<n-button
:loading=
"isLoading"
type=
"primary"
@
click=
"addSubject"
>
提交
</n-button>
</n-space>
</n-form>
</n-drawer-content>
</n-drawer>
</
template
>
</
template
>
<
script
>
<
script
>
...
@@ -69,6 +92,7 @@ export default {
...
@@ -69,6 +92,7 @@ export default {
const
formData
=
ref
({
const
formData
=
ref
({
propertyName
:
null
,
propertyName
:
null
,
relationId
:
null
,
relationId
:
null
,
systemId
:
null
,
})
})
const
showDrawer
=
ref
(
false
)
const
showDrawer
=
ref
(
false
)
const
isLoading
=
ref
(
false
)
const
isLoading
=
ref
(
false
)
...
@@ -76,20 +100,32 @@ export default {
...
@@ -76,20 +100,32 @@ export default {
const
relationOptions
=
ref
([])
const
relationOptions
=
ref
([])
const
systemOptions
=
ref
([])
const
systemOptions
=
ref
([])
const
data
=
ref
([])
const
data
=
ref
([])
function
getData
()
{
const
subjectNodes
=
ref
([])
function
fetchSubjects
()
{
// ajax
// .get({
// url: api.GET_NODES,
// params: { nodeId: '572563400077869056' },
// })
// .then((res) => {
// console.log('nodes:', res)
// data.value = res.data.content
// systemOptions.value = data.value.nodes
// .filter((node) => node.nodeLabel === 'System')
// .map((node) => ({ label: node.systemName, value: node.nodeId }))
// })
ajax
ajax
.
get
({
.
get
({
url
:
api
.
GET_
NODE
S
,
url
:
api
.
GET_
SUBJECT
S
,
})
})
.
then
((
res
)
=>
{
.
then
((
res
)
=>
{
console
.
log
(
'nodes:'
,
res
)
console
.
log
(
'subject'
,
res
.
data
.
content
)
data
.
value
=
res
.
data
.
content
subjectNodes
.
value
=
res
.
data
.
content
systemOptions
.
value
=
data
.
value
.
nodes
data
.
value
=
{
nodes
:
subjectNodes
.
value
,
links
:
[]
}
.
filter
((
node
)
=>
node
.
nodeLabel
===
'System'
)
.
map
((
node
)
=>
({
label
:
node
.
systemName
,
value
:
node
.
nodeId
}))
})
})
}
}
getData
()
fetchSubjects
()
ajax
ajax
.
get
({
.
get
({
url
:
api
.
GET_RELATIONS
,
url
:
api
.
GET_RELATIONS
,
...
@@ -101,18 +137,32 @@ export default {
...
@@ -101,18 +137,32 @@ export default {
value
:
item
.
id
,
value
:
item
.
id
,
}))
}))
})
})
function
handleBranch
({
nodeId
}
)
{
function
fetchSubordinates
(
params
=
null
)
{
ajax
ajax
.
get
({
.
get
({
url
:
api
.
GET_NODES
,
url
:
api
.
GET_NODES
,
params
:
{
nodeId
}
,
params
,
})
})
.
then
((
res
)
=>
{
.
then
((
res
)
=>
{
console
.
log
(
'nodes:'
,
res
)
const
{
links
,
nodes
}
=
res
.
data
.
content
// data.value = res.data.content
data
.
value
=
{
nodes
:
[
...
data
.
value
.
nodes
,
...
nodes
.
filter
((
node
)
=>
node
.
nodeLabel
!==
'Subject'
),
],
links
:
[...
data
.
value
.
links
,
...
links
],
}
systemOptions
.
value
=
data
.
value
.
nodes
.
filter
((
node
)
=>
node
.
nodeLabel
===
'System'
)
.
map
((
node
)
=>
({
label
:
node
.
systemName
,
value
:
node
.
nodeId
}))
})
})
}
}
function
handleAdd
({
nodeId
})
{
function
handleAdd
({
nodeId
})
{
formData
.
value
=
{
propertyName
:
null
,
relationId
:
null
,
systemId
:
null
,
}
subjectId
.
value
=
nodeId
subjectId
.
value
=
nodeId
showDrawer
.
value
=
true
showDrawer
.
value
=
true
}
}
...
@@ -133,7 +183,8 @@ export default {
...
@@ -133,7 +183,8 @@ export default {
},
},
})
})
.
then
(()
=>
{
.
then
(()
=>
{
getData
()
// fetchSubjects()
fetchSubordinates
({
nodeId
:
subjectId
.
value
})
isLoading
.
value
=
false
isLoading
.
value
=
false
showDrawer
.
value
=
false
showDrawer
.
value
=
false
message
.
success
(
'提交成功'
)
message
.
success
(
'提交成功'
)
...
@@ -152,11 +203,61 @@ export default {
...
@@ -152,11 +203,61 @@ export default {
negativeText
:
'取消'
,
negativeText
:
'取消'
,
maskClosable
:
false
,
maskClosable
:
false
,
onPositiveClick
:
()
=>
{
onPositiveClick
:
()
=>
{
console
.
log
(
'delete'
,
data
)
ajax
message
.
success
(
'删除成功!'
)
.
delete
({
url
:
api
.
DELETE_NODE
.
replace
(
'{id}'
,
data
.
id
),
})
.
then
(()
=>
{
if
(
data
.
nodeLabel
===
'Subject'
)
{
fetchSubjects
()
}
else
{
fetchSubordinates
({
nodeId
:
null
})
}
message
.
success
(
'删除成功!'
)
})
},
},
})
})
}
}
const
subjectFormRef
=
ref
(
null
)
const
showSubjectDrawer
=
ref
(
false
)
const
subjectData
=
ref
({
subjectName
:
null
})
const
addSubject
=
(
e
)
=>
{
e
.
preventDefault
()
subjectFormRef
.
value
.
validate
((
errors
)
=>
{
if
(
!
errors
)
{
isLoading
.
value
=
true
ajax
.
post
({
url
:
api
.
POST_SUBJECT
,
params
:
subjectData
.
value
,
})
.
then
(()
=>
{
fetchSubjects
()
isLoading
.
value
=
false
showSubjectDrawer
.
value
=
false
message
.
success
(
'提交成功'
)
})
}
})
}
const
handleSearch
=
(
key
)
=>
{
if
(
!
key
)
{
fetchSubjects
()
return
}
ajax
.
get
({
url
:
api
.
GET_NODES
,
params
:
{
nodeName
:
key
},
})
.
then
((
res
)
=>
{
data
.
value
=
res
.
data
.
content
systemOptions
.
value
=
data
.
value
.
nodes
.
filter
((
node
)
=>
node
.
nodeLabel
===
'System'
)
.
map
((
node
)
=>
({
label
:
node
.
systemName
,
value
:
node
.
nodeId
}))
})
}
return
{
return
{
formRef
,
formRef
,
formData
,
formData
,
...
@@ -167,35 +268,47 @@ export default {
...
@@ -167,35 +268,47 @@ export default {
systemOptions
,
systemOptions
,
data
,
data
,
mockData
,
mockData
,
handleBranch
,
fetchSubordinates
,
handleAdd
,
handleAdd
,
d3Ref
,
d3Ref
,
setKey
,
setKey
,
rules
:
{
rules
:
{
property
Name
:
[
subject
Name
:
[
{
{
required
:
true
,
required
:
true
,
message
:
'请输入
节点
名称'
,
message
:
'请输入名称'
,
trigger
:
[
'input'
,
'blur'
],
trigger
:
[
'input'
,
'blur'
],
},
},
],
],
relationId
:
[
propertyName
:
[
{
{
required
:
true
,
required
:
true
,
message
:
'请
选择从属类型
'
,
message
:
'请
输入节点名称
'
,
trigger
:
[
'input'
,
'blur'
],
trigger
:
[
'input'
,
'blur'
],
},
},
],
],
system
Id
:
[
relation
Id
:
[
{
{
required
:
true
,
required
:
true
,
message
:
'请选择
所属系统
'
,
message
:
'请选择
从属类型
'
,
trigger
:
[
'input'
,
'blur'
],
trigger
:
[
'input'
,
'blur'
],
},
},
],
],
// systemId: [
// {
// required: true,
// message: '请选择所属系统',
// trigger: ['input', 'blur'],
// },
// ],
},
},
curNode
,
curNode
,
handleDelete
,
handleDelete
,
showSubjectDrawer
,
subjectFormRef
,
subjectData
,
addSubject
,
handleSearch
,
}
}
},
},
}
}
...
@@ -209,7 +322,7 @@ export default {
...
@@ -209,7 +322,7 @@ export default {
overflow hidden
overflow hidden
grid-template-areas 'nav nav' 'side content' 'side footer'
grid-template-areas 'nav nav' 'side content' 'side footer'
grid-template-columns 0px 1fr
grid-template-columns 0px 1fr
grid-template-rows 0px 1fr 70px
grid-template-rows
4
0px 1fr 70px
padding 4px
padding 4px
font-weight bold !important
font-weight bold !important
</
style
>
</
style
>
src/components/nav.vue
View file @
bcfd01c7
<
template
>
<
template
>
<div
class=
"nav"
></div>
<div
class=
"nav"
>
<n-input
v-model:value=
"searchKey"
type=
"text"
placeholder=
"搜索Subject"
clearable
@
keypress
.
enter=
"search"
/>
</div>
</
template
>
</
template
>
<
script
>
<
script
>
import
{
defineComponent
}
from
'vue'
import
{
defineComponent
,
ref
}
from
'vue'
export
default
defineComponent
({
export
default
defineComponent
({
name
:
'Nav'
,
name
:
'Nav'
,
setup
()
{},
emits
:
[
'search'
],
setup
(
_
,
ctx
)
{
const
searchKey
=
ref
(
null
)
return
{
searchKey
,
search
:
()
=>
ctx
.
emit
(
'search'
,
searchKey
.
value
),
}
},
})
})
</
script
>
</
script
>
...
@@ -15,4 +30,5 @@ export default defineComponent({
...
@@ -15,4 +30,5 @@ export default defineComponent({
.nav
.nav
background #f9fbfd
background #f9fbfd
border-bottom 4px solid #fff
border-bottom 4px solid #fff
padding 0 10px
</
style
>
</
style
>
src/util/useD3.js
View file @
bcfd01c7
...
@@ -78,7 +78,7 @@ const defaultConfig = {
...
@@ -78,7 +78,7 @@ const defaultConfig = {
isHighLight
:
true
,
// 是否启动 鼠标 hover 到节点上高亮与节点有关的节点,其他无关节点透明的功能
isHighLight
:
true
,
// 是否启动 鼠标 hover 到节点上高亮与节点有关的节点,其他无关节点透明的功能
isScale
:
true
,
// 是否启用缩放平移zoom功能
isScale
:
true
,
// 是否启用缩放平移zoom功能
scaleExtent
:
[
0.2
,
1.5
],
// 缩放的比例尺
scaleExtent
:
[
0.2
,
1.5
],
// 缩放的比例尺
chargeStrength
:
-
3
00
,
// 万有引力
chargeStrength
:
-
1
00
,
// 万有引力
collide
:
100
,
// 碰撞力的大小 (节点之间的间距)
collide
:
100
,
// 碰撞力的大小 (节点之间的间距)
alphaDecay
:
0.0228
,
// 控制力学模拟衰减率
alphaDecay
:
0.0228
,
// 控制力学模拟衰减率
r
:
45
,
// 圈圈的半径 [30 - 45]
r
:
45
,
// 圈圈的半径 [30 - 45]
...
@@ -86,8 +86,8 @@ const defaultConfig = {
...
@@ -86,8 +86,8 @@ const defaultConfig = {
fontColor
:
'#2c3e50'
,
// 圈圈内文字的颜色
fontColor
:
'#2c3e50'
,
// 圈圈内文字的颜色
linkSrc
:
30
,
// 划线时候的弧度
linkSrc
:
30
,
// 划线时候的弧度
linkColor
:
'gray'
,
// 链接线默认的颜色
linkColor
:
'gray'
,
// 链接线默认的颜色
strokeColor
:
'
gray
'
,
// 圈圈外围包裹的颜色
strokeColor
:
'
rgba(255,255,255,0.4)
'
,
// 圈圈外围包裹的颜色
strokeWidth
:
0
,
// 圈圈外围包裹的宽度
strokeWidth
:
6
,
// 圈圈外围包裹的宽度
colorList
:
{
colorList
:
{
default
:
'skyblue'
,
default
:
'skyblue'
,
System
:
'#58b2dc'
,
System
:
'#58b2dc'
,
...
@@ -145,7 +145,8 @@ export default class RelationGraph {
...
@@ -145,7 +145,8 @@ export default class RelationGraph {
this
.
dependsNode
=
[]
this
.
dependsNode
=
[]
this
.
dependsLinkAndText
=
[]
this
.
dependsLinkAndText
=
[]
console
.
log
(
'init'
,
this
.
config
)
// console.log('init', this.config)
this
.
createSimulation
()
this
.
init
()
this
.
init
()
}
}
...
@@ -156,12 +157,202 @@ export default class RelationGraph {
...
@@ -156,12 +157,202 @@ export default class RelationGraph {
.
call
(
textWrap
,
this
.
config
.
r
*
1.8
)
.
call
(
textWrap
,
this
.
config
.
r
*
1.8
)
}
}
update
(
data
)
{
update
(
data
)
{
this
.
config
=
Object
.
assign
({},
this
.
config
,
data
)
const
self
=
this
console
.
log
(
'===='
,
data
)
// this.config = Object.assign({}, this.config, data)
this
.
config
.
nodes
=
[...
data
.
nodes
]
this
.
config
.
links
=
[...
data
.
links
]
console
.
log
(
'update'
,
this
.
config
)
console
.
log
(
'update'
,
this
.
config
)
this
.
createSimulation
()
// d3.selectAll('pattern.circle-bg').data(this.config.nodes)
d3
.
selectAll
(
'pattern.circle-bg'
).
data
(
this
.
config
.
nodes
)
// d3.selectAll('g.circle-wrapper').data(this.config.nodes)
d3
.
selectAll
(
'g.circle-wrapper'
).
data
(
this
.
config
.
nodes
)
// d3.selectAll('g.edge').data(this.config.links)
d3
.
selectAll
(
'g.edge'
).
data
(
this
.
config
.
links
)
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
.
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'
])
// 给圈圈节点添加g便于后面添加menu
this
.
circlesWrapper
=
this
.
relMap_g
.
selectAll
(
'g.circle-wrapper'
)
.
data
(
this
.
config
.
nodes
)
.
enter
()
.
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
.
SVG
.
selectAll
(
'text.node-text'
).
call
(
textWrap
,
this
.
config
.
r
*
1.8
)
// 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
.
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
)
this
.
simulation
.
restart
()
}
}
openMenu
(
self
,
d
,
type
)
{
openMenu
(
self
,
d
,
type
)
{
this
.
setCurNode
(
d
)
this
.
setCurNode
(
d
)
...
@@ -184,7 +375,7 @@ export default class RelationGraph {
...
@@ -184,7 +375,7 @@ export default class RelationGraph {
// 创建力学模拟器
// 创建力学模拟器
createSimulation
()
{
createSimulation
()
{
console
.
log
(
'createSimulation'
,
this
.
config
.
nodes
)
console
.
log
(
'createSimulation'
,
this
.
config
.
nodes
,
this
.
config
.
links
)
// 1. 创建一个力学模拟器
// 1. 创建一个力学模拟器
this
.
simulation
=
d3
this
.
simulation
=
d3
.
forceSimulation
(
this
.
config
.
nodes
)
.
forceSimulation
(
this
.
config
.
nodes
)
...
@@ -213,7 +404,7 @@ export default class RelationGraph {
...
@@ -213,7 +404,7 @@ export default class RelationGraph {
init
()
{
init
()
{
const
self
=
this
const
self
=
this
this
.
createSimulation
()
//
this.createSimulation()
// 2.创建svg标签
// 2.创建svg标签
this
.
SVG
=
this
.
graph
this
.
SVG
=
this
.
graph
...
@@ -237,8 +428,8 @@ export default class RelationGraph {
...
@@ -237,8 +428,8 @@ export default class RelationGraph {
this
.
defs
=
this
.
SVG
.
append
(
'defs'
)
this
.
defs
=
this
.
SVG
.
append
(
'defs'
)
// 3.1 添加箭头
// 3.1 添加箭头
const
border
=
const
border
=
7.5
this
.
config
.
strokeWidth
==
0
?
7.5
:
1.8
*
this
.
config
.
strokeWidth
//const border =
this.config.strokeWidth == 0 ? 7.5 : 1.8 * this.config.strokeWidth
this
.
marker
=
this
.
defs
this
.
marker
=
this
.
defs
.
append
(
'marker'
)
.
append
(
'marker'
)
.
attr
(
'id'
,
'marker'
)
.
attr
(
'id'
,
'marker'
)
...
@@ -290,7 +481,6 @@ export default class RelationGraph {
...
@@ -290,7 +481,6 @@ export default class RelationGraph {
.
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.关系图添加线
// 5.1 每条线是个容器,有线 和一个装文字的容器
// 5.1 每条线是个容器,有线 和一个装文字的容器
this
.
edges
=
this
.
relMap_g
this
.
edges
=
this
.
relMap_g
...
@@ -337,7 +527,7 @@ export default class RelationGraph {
...
@@ -337,7 +527,7 @@ export default class RelationGraph {
.
append
(
'rect'
)
.
append
(
'rect'
)
.
attr
(
'x'
,
40
)
.
attr
(
'x'
,
40
)
.
attr
(
'y'
,
-
10
)
.
attr
(
'y'
,
-
10
)
.
attr
(
'width'
,
4
0
)
.
attr
(
'width'
,
5
0
)
.
attr
(
'height'
,
20
)
.
attr
(
'height'
,
20
)
.
attr
(
'fill'
,
'#f9fbfd'
)
.
attr
(
'fill'
,
'#f9fbfd'
)
.
attr
(
'stroke'
,
'transparent'
)
.
attr
(
'stroke'
,
'transparent'
)
...
@@ -379,7 +569,8 @@ export default class RelationGraph {
...
@@ -379,7 +569,8 @@ export default class RelationGraph {
'stroke-width'
,
'stroke-width'
,
self
.
config
.
strokeWidth
==
0
?
3
:
1.5
*
self
.
config
.
strokeWidth
self
.
config
.
strokeWidth
==
0
?
3
:
1.5
*
self
.
config
.
strokeWidth
)
)
d3
.
select
(
this
).
attr
(
'stroke'
,
d
.
strokeColor
||
self
.
config
.
strokeColor
)
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
)
{
if
(
self
.
config
.
isHighLight
)
{
self
.
highlightObject
(
d
)
self
.
highlightObject
(
d
)
}
}
...
...
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