Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
V
vue-gojs
Overview
Overview
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
吴斌
vue-gojs
Commits
c0665cb0
Commit
c0665cb0
authored
Oct 09, 2023
by
吴斌
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
update:路径寻找,高亮显示。同时分离公共代码。
parent
85ac5828
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
241 additions
and
117 deletions
+241
-117
App.vue
src/App.vue
+12
-104
analyze-data.vue
src/components/info/analyze-data.vue
+80
-0
source-collapse.vue
src/components/source-panel/source-collapse.vue
+2
-2
GOJSKit.ts
src/kit/GOJSKit.ts
+133
-0
LinkTemplateKit.ts
src/kit/LinkTemplateKit.ts
+14
-11
No files found.
src/App.vue
View file @
c0665cb0
...
...
@@ -17,6 +17,7 @@
<div
class=
"text-center m-4"
>
<el-button
@
click=
"analyseData"
>
数据分析
</el-button>
</div>
<AnalyzeData
class=
"w-full max-h-full"
:nodeMap=
"nodeMap"
:paths=
"paths"
:myDiagram=
"myDiagram"
></AnalyzeData>
</div>
</div>
<div
class=
"flex"
>
...
...
@@ -62,7 +63,7 @@ import * as go from "gojs";
import
SourceCollapse
from
"./components/source-panel/source-collapse.vue"
;
import
{
onMounted
,
ref
}
from
"vue"
;
import
{
picCategory
}
from
"./kit/ModelData.ts"
;
import
{
GO
,
makePort
,
showSmallPorts
}
from
"./kit/GOJSKit.ts"
;
import
{
findNodesAllWayBetween
,
getMapData
,
getSelectedNodes
,
GO
,
makePort
,
showSmallPorts
}
from
"./kit/GOJSKit.ts"
;
import
{
makeKitTopRotatingTool
,
nodeResizeAdornmentTemplate
,
nodeRotateAdornmentTemplate
,
...
...
@@ -71,6 +72,7 @@ import {
import
{
animateFlow
,
FlowLink
,
linkSelectionAdornmentTemplate
}
from
"./kit/LinkTemplateKit.ts"
;
import
{
Inspector
}
from
"./kit/DataInspector.ts"
;
import
{
ElMessage
}
from
"element-plus"
;
import
AnalyzeData
from
"./components/info/analyze-data.vue"
;
const
categoryList
:
any
=
ref
(
null
)
let
myDiagram
:
any
=
null
;
...
...
@@ -80,6 +82,9 @@ let inspector:any=null;
const
addProperty
=
ref
(
false
)
let
propertyForm
:
any
=
ref
(
null
);
let
nodeMap
=
ref
({});
let
paths
=
ref
<
any
[][]
>
([]);
function
showAddPropertyDialog
(){
let
node
=
myDiagram
.
selection
.
first
();
if
(
node
===
null
){
...
...
@@ -206,7 +211,7 @@ function initDiagram() {
new
go
.
Binding
(
"stroke"
,
"color"
).
makeTwoWay
(),
new
go
.
Binding
(
"fill"
,
"color"
),
),
GO
(
go
.
Shape
,
{
toArrow
:
"Standard"
,
stroke
:
null
}),
GO
(
go
.
Shape
,
{
toArrow
:
"Standard"
,
stroke
:
null
}
,
new
go
.
Binding
(
"fill"
,
"color"
)
),
GO
(
go
.
TextBlock
,
{
segmentIndex
:
0
,
segmentOffset
:
new
go
.
Point
(
NaN
,
NaN
),
segmentOrientation
:
go
.
Link
.
OrientUpright
,
editable
:
true
,
text
:
""
},
new
go
.
Binding
(
"text"
,
"from_text"
).
makeTwoWay
()
...
...
@@ -291,11 +296,12 @@ function importData() {
{
"from"
:
-
9
,
"points"
:[
-
460
,
-
5
,
-
460
,
5
,
-
460
,
19
,
-
513
,
19
,
-
566
,
19
,
-
576
,
19
],
"from_text"
:
""
,
"middle_text"
:
""
,
"to_text"
:
"氨产品"
,
"category"
:
"Arrow"
},
{
"from"
:
-
4
,
"to"
:
-
10
,
"points"
:[
-
140
,
250
,
-
130
,
250
,
200
,
250
,
200
,
165
,
200
,
80
,
200
,
70
],
"category"
:
"Arrow"
},
{
"from"
:
-
4
,
"to"
:
-
2
,
"points"
:[
-
170
,
220
,
-
170
,
210
,
-
170
,
197
,
-
20
,
197
,
-
20
,
150
,
-
20
,
140
],
"category"
:
"Arrow"
},
{
"from"
:
-
10
,
"to"
:
-
2
,
"points"
:[
150
,
20
,
140
,
20
,
125
,
20
,
125
,
20
,
110
,
20
,
100
,
20
],
"category"
:
"
Fl
ow"
},
{
"from"
:
-
8
,
"to"
:
-
2
,
"points"
:[
-
170
,
-
25
,
-
170
,
-
35
,
-
170
,
-
166
,
-
20
,
-
166
,
-
20
,
-
110
,
-
20
,
-
100
],
"category"
:
"
Fl
ow"
},
{
"from"
:
-
10
,
"to"
:
-
2
,
"points"
:[
150
,
20
,
140
,
20
,
125
,
20
,
125
,
20
,
110
,
20
,
100
,
20
],
"category"
:
"
Arr
ow"
},
{
"from"
:
-
8
,
"to"
:
-
2
,
"points"
:[
-
170
,
-
25
,
-
170
,
-
35
,
-
170
,
-
166
,
-
20
,
-
166
,
-
20
,
-
110
,
-
20
,
-
100
],
"category"
:
"
Arr
ow"
},
{
"from"
:
-
1
,
"points"
:[
-
135
,
370
,
-
125
,
370
,
-
97.3671875
,
370
,
-
97.3671875
,
370
,
-
69.734375
,
370
,
-
59.734375
,
370
],
"category"
:
"Arrow"
}
]}
);
nodeMap
.
value
=
getMapData
(
myDiagram
)
}
function
exportData
()
{
...
...
@@ -304,8 +310,7 @@ function exportData() {
}
function
analyseData
(){
let
selectedNodes
=
getSelectedNodes
()
console
.
log
(
"选择的节点"
,
selectedNodes
)
let
selectedNodes
=
getSelectedNodes
(
myDiagram
)
if
(
selectedNodes
.
length
!=
2
){
ElMessage
.
error
(
"只能选择两个节点"
)
...
...
@@ -315,105 +320,9 @@ function analyseData(){
let
start_node
=
myDiagram
.
findNodeForKey
(
selectedNodes
[
0
].
key
)
let
end_node
=
myDiagram
.
findNodeForKey
(
selectedNodes
[
1
].
key
)
findNodesAllWayBetween
(
start_node
.
data
.
key
,
end_node
.
data
.
key
)
paths
.
value
=
findNodesAllWayBetween
(
start_node
.
data
.
key
,
end_node
.
data
.
key
,
myDiagram
)
}
// 寻找两个节点间的所有路径
function
findNodesAllWayBetween
(
startKey
:
number
,
endKey
:
number
){
// 保存所有路径
let
paths
=
[[
startKey
]],
// 搜索是否完成
flag
:
boolean
=
false
,
nodeLinkMap
=
getMapData
();
while
(
!
flag
){
// 保存当前路径的节点数量
let
beforePathsNode
=
0
;
// 保存扩展后路径的节点数量
let
afterPathsNode
=
0
;
// 计算扩展前的总路径节点数量
for
(
let
path
of
paths
){
beforePathsNode
+=
path
.
length
}
for
(
let
path
of
paths
){
// 获取当前路径的最后一个节点
let
lastNode
=
path
[
path
.
length
-
1
]
// 如果最后一个节点是终点,则跳过,无需扩展
if
(
lastNode
==
endKey
){
continue
}
// 获取当前路径最后一个节点的下一个节点
let
nextNode
=
nodeLinkMap
[
lastNode
].
next
// 如果没有下一个节点,则跳过,无需扩展
if
(
nextNode
.
length
==
0
){
continue
}
// 如果只有一个节点,则将下一个节点直接加入当前路径
if
(
nextNode
.
length
==
1
){
path
.
push
(
nextNode
[
0
])
}
// 如果有多个节点,则将当前路径分裂为多个路径
else
{
for
(
let
nextNodeKey
of
nextNode
){
// 如果下一个节点已经在路径中,则跳过,无需扩展,避免循环
if
(
nextNodeKey
in
path
){
continue
}
let
newPath
=
path
.
slice
(
0
)
newPath
.
push
(
nextNodeKey
)
paths
.
push
(
newPath
)
}
// 删除没有扩展的原路径
paths
=
paths
.
filter
((
item
:
any
)
=>
item
!=
path
)
}
}
// 计算扩展后的总路径节点数量
for
(
let
path
of
paths
){
afterPathsNode
+=
path
.
length
}
// 如果paths内元素数量没有增加,则搜索完成
if
(
beforePathsNode
==
afterPathsNode
){
flag
=
true
// 删除没有找到终点的路径
paths
=
paths
.
filter
((
item
:
any
)
=>
item
[
item
.
length
-
1
]
==
endKey
)
}
}
return
paths
}
function
getSelectedNodes
()
{
let
selectObjIterator
=
myDiagram
.
selection
.
iterator
;
let
resultNodes
=
[];
while
(
selectObjIterator
.
next
())
{
let
selectedObj
=
selectObjIterator
.
value
;
if
(
selectedObj
instanceof
go
.
Node
)
{
resultNodes
.
push
(
selectedObj
.
data
);
}
}
return
resultNodes
;
}
function
getMapData
()
{
/*
* {key:{next:[], data:{}}}
*/
let
model
=
myDiagram
.
model
let
nodeDataArray
=
model
.
nodeDataArray
let
linkDataArray
=
model
.
linkDataArray
let
nodeMap
=
{}
nodeDataArray
.
forEach
((
item
:
any
)
=>
{
nodeMap
[
item
.
key
]
=
{
next
:[],
data
:
item
}
})
linkDataArray
.
forEach
((
item
:
any
)
=>
{
let
node
=
null
;
if
(
item
.
from
&&
item
.
to
){
node
=
nodeMap
[
item
.
from
]
node
.
next
.
push
(
item
.
to
)
}
})
return
nodeMap
}
function
changeData
(){
let
model
=
myDiagram
.
model
...
...
@@ -429,7 +338,6 @@ function changeData(){
},
5000
)
}
onMounted
(()
=>
{
initPalette
();
initDiagram
();
...
...
src/components/info/analyze-data.vue
0 → 100644
View file @
c0665cb0
<
template
>
<div>
<div
class=
"text-center"
v-show=
"paths.length === 0"
>
暂无分析数据
</div>
<div
v-show=
"paths.length > 0"
>
<div>
线路结果
</div>
<el-scrollbar
max-height=
"200px"
>
<el-collapse>
<el-collapse-item
class=
"m-2"
v-for=
"(value, key) in pathNodesMap"
:title=
"'线路' + key "
>
<el-form>
<el-form-item
label=
"路线"
>
{{
value
.
nodesName
}}
</el-form-item>
<el-form-item
label=
"权重"
>
<el-input
v-model=
"value.weight"
></el-input>
</el-form-item>
</el-form>
<div
class=
"flex justify-center"
>
<el-checkbox
@
change=
"highlightPath(key)"
v-model=
"value.highlight"
>
高亮
</el-checkbox>
<el-button
type=
"primary"
>
确定
</el-button>
</div>
</el-collapse-item>
</el-collapse>
</el-scrollbar>
<div>
分析结果
</div>
<div
class=
"w-full h-26 bg-red-200"
>
</div>
</div>
</div>
</
template
>
<
script
setup
lang=
"ts"
>
import
{
ref
,
watch
}
from
"vue"
;
import
{
highlightLink
,
cancelHighlightLink
}
from
"../../kit/GOJSKit"
;
const
props
=
defineProps
({
paths
:
{
type
:
Array
,
default
:
[]
},
nodeMap
:{
type
:
Object
,
default
:
{}
},
myDiagram
:{
type
:
Object
,
}
})
let
pathNodesMap
=
ref
<
Record
<
string
,
any
>>
({})
watch
(()
=>
props
.
paths
,
(
newValue
)
=>
{
newValue
.
forEach
((
path
:
any
)
=>
{
let
pathNode
:
any
[]
=
[]
let
pathNodeName
:
string
[]
=
[]
path
.
forEach
((
node
:
any
)
=>
{
pathNode
.
push
(
props
.
nodeMap
[
node
])
pathNodeName
.
push
(
props
.
nodeMap
[
node
].
data
.
name
)
})
pathNodesMap
.
value
[
newValue
.
indexOf
(
path
)
+
1
]
=
{
'nodeKeys'
:
path
,
'nodesName'
:
pathNodeName
,
"nodes"
:
pathNode
,
'highlight'
:
false
,
'weight'
:
1
}
})
});
function
highlightPath
(
pathIndex
:
string
){
let
path
:
number
[]
=
pathNodesMap
.
value
[
pathIndex
].
nodeKeys
cancelHighlightLink
(
props
.
myDiagram
)
for
(
let
i
=
0
;
i
<
path
.
length
-
1
;
i
++
)
{
if
(
pathNodesMap
.
value
[
pathIndex
].
highlight
)
{
highlightLink
(
path
[
i
],
path
[
i
+
1
],
props
.
myDiagram
)
}
}
}
function
computeData
(){
}
</
script
>
\ No newline at end of file
src/components/source-panel/source-collapse.vue
View file @
c0665cb0
...
...
@@ -18,8 +18,8 @@ const props = defineProps({
}
})
var
sourcePalette
:
any
=
ref
(
null
)
var
sourceModel
:
any
=
ref
(
null
)
let
sourcePalette
:
any
=
ref
(
null
)
let
sourceModel
:
any
=
ref
(
null
)
function
init
(){
sourcePalette
=
GO
(
go
.
Palette
,
props
.
picture_category
,
{
...
...
src/kit/GOJSKit.ts
View file @
c0665cb0
import
{
log
}
from
'console'
;
import
go
from
'gojs'
;
export
var
GO
=
go
.
GraphObject
.
make
;
...
...
@@ -23,6 +24,7 @@ export function makePort(name:any, spot:any, output:any, input:any) {
cursor
:
"pointer"
});
}
/**
* 展示连接锚点
* @param {Node} node 节点
...
...
@@ -36,3 +38,133 @@ export function showSmallPorts(node:any, show:any) {
});
}
/**
* 获取节点的所有连接,存储为一个Map。{key:{next:[], data:{}}}
*/
export
function
getMapData
(
myDiagram
:
any
)
{
let
model
=
myDiagram
.
model
let
nodeDataArray
=
model
.
nodeDataArray
let
linkDataArray
=
model
.
linkDataArray
let
nodeMap
:
Record
<
any
,
any
>
=
{}
nodeDataArray
.
forEach
((
item
:
any
)
=>
{
nodeMap
[
item
.
key
]
=
{
next
:[],
data
:
item
}
})
linkDataArray
.
forEach
((
item
:
any
)
=>
{
let
node
=
null
;
if
(
item
.
from
&&
item
.
to
){
node
=
nodeMap
[
item
.
from
]
node
.
next
.
push
(
item
.
to
)
}
})
return
nodeMap
}
/**
* 获取所有选择的节点
* @param {go.Diagram} myDiagram
* @return [{},{}]
*/
export
function
getSelectedNodes
(
myDiagram
:
go
.
Diagram
)
{
let
selectObjIterator
=
myDiagram
.
selection
.
iterator
;
let
resultNodes
=
[];
while
(
selectObjIterator
.
next
())
{
let
selectedObj
=
selectObjIterator
.
value
;
if
(
selectedObj
instanceof
go
.
Node
)
{
resultNodes
.
push
(
selectedObj
.
data
);
}
}
return
resultNodes
;
}
/**
* 获取选中的两点间的所有路径
* @param startKey
* @param endKey
* @param myDiagram
*/
export
function
findNodesAllWayBetween
(
startKey
:
number
,
endKey
:
number
,
myDiagram
:
go
.
Diagram
)
{
// 保存所有路径
let
paths
=
[[
startKey
]],
// 搜索是否完成
flag
:
boolean
=
false
,
nodeLinkMap
=
getMapData
(
myDiagram
);
while
(
!
flag
){
// 保存当前路径的节点数量
let
beforePathsNode
=
0
;
// 保存扩展后路径的节点数量
let
afterPathsNode
=
0
;
// 计算扩展前的总路径节点数量
for
(
let
path
of
paths
){
beforePathsNode
+=
path
.
length
}
for
(
let
path
of
paths
){
// 获取当前路径的最后一个节点
let
lastNode
=
path
[
path
.
length
-
1
]
// 如果最后一个节点是终点,则跳过,无需扩展
if
(
lastNode
==
endKey
){
continue
}
// 获取当前路径最后一个节点的下一个节点
let
nextNode
=
nodeLinkMap
[
lastNode
].
next
// 如果没有下一个节点,则跳过,无需扩展
if
(
nextNode
.
length
==
0
){
continue
}
// 如果只有一个节点,则将下一个节点直接加入当前路径
if
(
nextNode
.
length
==
1
){
path
.
push
(
nextNode
[
0
])
}
// 如果有多个节点,则将当前路径分裂为多个路径
else
{
for
(
let
nextNodeKey
of
nextNode
){
// 如果下一个节点已经在路径中,则跳过,无需扩展,避免循环
if
(
nextNodeKey
in
path
){
continue
}
let
newPath
=
path
.
slice
(
0
)
newPath
.
push
(
nextNodeKey
)
paths
.
push
(
newPath
)
}
// 删除没有扩展的原路径
paths
=
paths
.
filter
((
item
:
any
)
=>
item
!=
path
)
}
}
// 计算扩展后的总路径节点数量
for
(
let
path
of
paths
){
afterPathsNode
+=
path
.
length
}
// 如果paths内元素数量没有增加,则搜索完成
if
(
beforePathsNode
==
afterPathsNode
){
flag
=
true
// 删除没有找到终点的路径
paths
=
paths
.
filter
((
item
:
any
)
=>
item
[
item
.
length
-
1
]
==
endKey
)
}
}
return
paths
}
/**
* 根据 from 和 to 高亮某条线
*/
export
function
highlightLink
(
from
:
number
,
to
:
number
,
myDiagram
:
any
){
let
model
=
myDiagram
.
model
let
linkDataArray
=
model
.
linkDataArray
linkDataArray
.
forEach
((
item
:
any
)
=>
{
if
(
item
.
from
==
from
&&
item
.
to
==
to
){
model
.
set
(
item
,
"color"
,
"red"
)
}
})
console
.
log
(
linkDataArray
);
}
export
function
cancelHighlightLink
(
myDiagram
:
any
){
let
model
=
myDiagram
.
model
let
linkDataArray
=
model
.
linkDataArray
linkDataArray
.
forEach
((
item
:
any
)
=>
{
model
.
set
(
item
,
"color"
,
"black"
)
})
}
\ No newline at end of file
src/kit/LinkTemplateKit.ts
View file @
c0665cb0
import
{
GO
}
from
'./GOJSKit'
import
go
from
'gojs'
import
{
log
}
from
"util"
;
export
var
linkSelectionAdornmentTemplate
=
GO
(
go
.
Adornment
,
"Link"
,
...
...
@@ -11,23 +10,22 @@ GO(go.Adornment, "Link",
);
export
function
MultiArrowLink
()
{
export
function
MultiArrowLink
(
this
:
go
.
Link
)
{
go
.
Link
.
call
(
this
);
// return GO(go.Link, {stroke:"red"})
}
go
.
Diagram
.
inherit
(
MultiArrowLink
,
go
.
Link
);
MultiArrowLink
.
prototype
.
makeGeometry
=
function
()
{
// get the Geometry created by the standard behavior
let
geo
=
go
.
Link
.
prototype
.
makeGeometry
.
call
(
this
);
if
(
geo
.
type
!==
go
.
Geometry
.
Path
||
geo
.
figures
.
length
===
0
)
return
geo
;
let
main
fig
=
geo
.
figures
.
elt
(
0
);
// assume there's just one PathFigure
let
mainsegs
=
mainfig
.
segments
;
let
main
Figure
=
geo
.
figures
.
elt
(
0
);
// assume there's just one PathFigure
let
pathSegments
=
mainFigure
.
segments
;
let
arrowLen
=
8
;
// length for each arrowhead
let
arrowWid
=
3
;
// actually half-width of each arrowhead
let
fx
=
main
fig
.
startX
;
let
fy
=
main
fig
.
startY
;
for
(
let
i
=
0
;
i
<
mainseg
s
.
length
;
i
++
)
{
let
a
=
mainseg
s
.
elt
(
i
);
let
fx
=
main
Figure
.
startX
;
let
fy
=
main
Figure
.
startY
;
for
(
let
i
=
0
;
i
<
pathSegment
s
.
length
;
i
++
)
{
let
a
=
pathSegment
s
.
elt
(
i
);
// assume each arrowhead is a simple triangle
let
ax
=
a
.
endX
;
let
ay
=
a
.
endY
;
...
...
@@ -79,8 +77,13 @@ export function animateFlow(myDiagram:go.Diagram){
// Animate the flow in the pipes
let
myAnimation
=
new
go
.
Animation
();
myAnimation
.
easing
=
go
.
Animation
.
EaseLinear
;
myDiagram
.
links
.
each
(
link
=>
link
.
findObject
(
"FLOW"
)?
myAnimation
.
add
(
link
.
findObject
(
"FLOW"
),
"strokeDashOffset"
,
20
,
0
):
null
);
myDiagram
.
links
.
each
(
link
=>
console
.
log
(
link
))
myDiagram
.
links
.
each
(
link
=>
{
let
shape
=
link
.
findObject
(
"FLOW"
)
if
(
shape
instanceof
go
.
GraphObject
){
myAnimation
.
add
(
shape
,
"strokeDashOffset"
,
20
,
0
)
}
}
);
// Run indefinitely
myAnimation
.
runCount
=
Infinity
;
myAnimation
.
start
();
...
...
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