Event Handling
You can capture events that occur in v-network-graph by specifying the events and functions to be captured in the event-handlers
attribute.
For a list of events that can be captured, see here.
Capture all events
If you specify "*" as the event type, all available events will be captured.
<script setup lang="ts">
import { reactive } from "vue"
import * as vNG from "v-network-graph"
import { format } from "date-fns/format"
import data from "./data"
const EVENTS_COUNT = 6
const eventLogs = reactive<[string, string, string][]>([])
const eventHandlers: vNG.EventHandlers = {
// wildcard: capture all events
"*": (type, event) => {
const timestamp = format(new Date(), "HH:mm:ss.SSS")
if (eventLogs.length > EVENTS_COUNT) {
eventLogs.splice(EVENTS_COUNT, eventLogs.length - EVENTS_COUNT)
}
if (event instanceof Object && "event" in event) {
Object.assign(event, { event: "(...)" })
}
eventLogs.unshift([timestamp, type, JSON.stringify(event)])
},
}
</script>
<template>
<v-network-graph
:nodes="data.nodes"
:edges="data.edges"
:layouts="data.layouts"
:configs="data.configs"
:event-handlers="eventHandlers"
/>
<div class="event-logs">
<div
v-for="[timestamp, type, log] in eventLogs"
:key="`${timestamp}/${type}/${log}`"
>
{{ timestamp }}
<span class="event-type">{{ type }}</span>
{{ log }}
</div>
</div>
</template>
<style lang="css" scoped>
.event-logs {
position: absolute;
inset: auto 10px 10px auto;
margin-left: 10px;
padding: 10px;
background: #ffff0044;
border-radius: 4px;
font-size: 11px;
font-family: monospace;
line-height: 11px;
pointer-events: none;
}
.event-logs div {
word-break: break-all;
}
.event-type {
font-weight: bold;
}
</style>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
import { Nodes, Edges, Layouts, defineConfigs } from "v-network-graph"
const nodes: Nodes = {
node1: { name: "N1" },
node2: { name: "N2" },
node3: { name: "N3" },
}
const edges: Edges = {
edge1: { source: "node1", target: "node2" },
edge2: { source: "node2", target: "node3" },
edge3: { source: "node3", target: "node1" },
}
const layouts: Layouts = {
nodes: {
node1: { x: 50, y: 0 },
node2: { x: 0, y: 75 },
node3: { x: 100, y: 75 },
},
}
const configs = defineConfigs({
node: {
selectable: true,
},
edge: {
selectable: true,
},
})
export default {
nodes,
edges,
layouts,
configs,
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
Handle user clicking on a node
The following is an example of specifying a handler that catches only the specified events.
In this example, the color of the badge changes when the node is clicked.
<script setup lang="ts">
import { reactive, ref } from "vue"
import * as vNG from "v-network-graph"
import data from "./data"
// additional layers definition
const layers = {
// {layername}: {position}
badge: "nodes",
}
const nodes = reactive({ ...data.nodes })
// wrap with ref() for immediate response to value changes
const layouts = ref({ ...data.layouts })
const edges = data.edges
const configs = data.configs
const eventHandlers: vNG.EventHandlers = {
"node:click": ({ node }) => {
// toggle
nodes[node].active = !nodes[node].active
},
}
</script>
<template>
<v-network-graph
:nodes="nodes"
:edges="edges"
:layouts="layouts"
:configs="configs"
:layers="layers"
:event-handlers="eventHandlers"
>
<!-- Additional layer -->
<template #badge="{ scale }">
<!--
If the `view.scalingObjects` config is `false`(default),
scaling does not change the display size of the nodes/edges.
The `scale` is passed as a scaling factor to implement
this behavior. -->
<circle
v-for="(pos, node) in layouts.nodes"
:key="node"
:cx="pos.x + 9 * scale"
:cy="pos.y - 9 * scale"
:r="4 * scale"
:fill="nodes[node].active ? '#00cc00' : '#ff5555'"
style="pointer-events: none"
/>
</template>
</v-network-graph>
</template>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
import { Nodes, Edges, Layouts, defineConfigs } from "v-network-graph"
const nodes: Nodes = {
node1: { name: "Node 1", active: true },
node2: { name: "Node 2", active: false },
node3: { name: "Node 3", active: true },
node4: { name: "Node 4", active: false },
}
const edges: Edges = {
edge1: { source: "node1", target: "node2" },
edge2: { source: "node2", target: "node3" },
edge3: { source: "node3", target: "node4" },
}
const layouts: Layouts = {
nodes: {
node1: { x: 0, y: 0 },
node2: { x: 80, y: 80 },
node3: { x: 160, y: 0 },
node4: { x: 240, y: 80 },
},
}
const configs = defineConfigs({
node: {
normal: {
type: "rect",
width: 32,
height: 32,
borderRadius: 6,
color: "#ffffff",
strokeWidth: 1,
strokeColor: "#888888",
},
hover: {
color: "#eeeeee",
},
},
edge: {
normal: {
width: 1,
color: "#666666",
},
hover: {
color: "#666666",
},
},
})
export default {
nodes,
edges,
layouts,
configs,
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
TIP
The handler for mouse events such as click are also passed a raw event object. By using this event object, it is possible to check if a modifier key (Ctrl, Alt, etc.) is pressed or not.
import { EventHandlers } from "v-network-graph"
const eventHandlers: EventHandlers = {
"node:click": ({ node, event }) => {
if (event.ctrlKey) {
// ...
}
}
}
2
3
4
5
6
7
8
Context menu
v-network-graph does not have the ability to show a context menu, but it can capture the right-clicking event ("contextmenu"
event) on objects of the network graph. From this event, a standard Event
object is obtained. You can combine your own components or other libraries to display the menu.
<script setup lang="ts">
import { ref } from "vue"
import * as vNG from "v-network-graph"
import data from "./data"
function showContextMenu(element: HTMLElement, event: MouseEvent) {
element.style.left = event.x + "px"
element.style.top = event.y + "px"
element.style.visibility = "visible"
const handler = (event: PointerEvent) => {
if (!event.target || !element.contains(event.target as HTMLElement)) {
element.style.visibility = "hidden"
document.removeEventListener("pointerdown", handler, { capture: true })
}
}
document.addEventListener("pointerdown", handler, { passive: true, capture: true })
}
const viewMenu = ref<HTMLDivElement>()
function showViewContextMenu(params: vNG.ViewEvent<MouseEvent>) {
const { event } = params
// Disable browser's default context menu
event.stopPropagation()
event.preventDefault()
if (viewMenu.value) {
showContextMenu(viewMenu.value, event)
}
}
const nodeMenu = ref<HTMLDivElement>()
const menuTargetNode = ref("")
function showNodeContextMenu(params: vNG.NodeEvent<MouseEvent>) {
const { node, event } = params
// Disable browser's default context menu
event.stopPropagation()
event.preventDefault()
if (nodeMenu.value) {
menuTargetNode.value = data.nodes[node].name ?? ""
showContextMenu(nodeMenu.value, event)
}
}
const edgeMenu = ref<HTMLDivElement>()
const menuTargetEdges = ref<string[]>([])
function showEdgeContextMenu(params: vNG.EdgeEvent<MouseEvent>) {
const { event } = params
// Disable browser's default context menu
event.stopPropagation()
event.preventDefault()
if (edgeMenu.value) {
menuTargetEdges.value = params.summarized ? params.edges : [params.edge]
showContextMenu(edgeMenu.value, event)
}
}
const eventHandlers: vNG.EventHandlers = {
"view:contextmenu": showViewContextMenu,
"node:contextmenu": showNodeContextMenu,
"edge:contextmenu": showEdgeContextMenu,
}
</script>
<template>
<div>
<v-network-graph
:nodes="data.nodes"
:edges="data.edges"
:layouts="data.layouts"
:configs="data.configs"
:event-handlers="eventHandlers"
/>
<div ref="viewMenu" class="context-menu">Menu for the background</div>
<div ref="nodeMenu" class="context-menu">
Menu for the nodes
<div>{{ menuTargetNode }}</div>
</div>
<div ref="edgeMenu" class="context-menu">
Menu for the edges
<div>{{ menuTargetEdges.join(", ") }}</div>
</div>
</div>
</template>
<style lang="scss" scoped>
.context-menu {
width: 180px;
background-color: #efefef;
padding: 10px;
position: fixed;
visibility: hidden;
font-size: 12px;
border: 1px solid #aaa;
box-shadow: 2px 2px 2px #aaa;
> div {
border: 1px dashed #aaa;
padding: 4px;
margin-top: 8px;
}
}
</style>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
import { Nodes, Edges, Layouts, defineConfigs } from "v-network-graph"
const nodes: Nodes = {
node1: { name: "Node 1" },
node2: { name: "Node 2" },
node3: { name: "Node 3" },
node4: { name: "Node 4" },
}
const edges: Edges = {
edge1: { source: "node1", target: "node2" },
edge2: { source: "node2", target: "node3" },
edge3: { source: "node3", target: "node4" },
edge4: { source: "node3", target: "node4" },
edge5: { source: "node3", target: "node4" },
edge6: { source: "node3", target: "node4" },
edge7: { source: "node3", target: "node4" },
edge8: { source: "node3", target: "node4" },
edge9: { source: "node3", target: "node4" },
edge10: { source: "node3", target: "node4" },
edge11: { source: "node3", target: "node4" },
edge12: { source: "node3", target: "node4" },
}
const layouts: Layouts = {
nodes: {
node1: { x: 0, y: 0 },
node2: { x: 80, y: 80 },
node3: { x: 160, y: 0 },
node4: { x: 240, y: 80 },
},
}
const configs = defineConfigs({
edge: {
normal: {
width: 3,
},
},
})
export default {
nodes,
edges,
layouts,
configs,
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
Tooltip
By combining event handling and coordinate translation, it is possible to represent a combination of DOM elements such as tooltip.
<script setup lang="ts">
import { computed, ref, watch } from "vue"
import * as vNG from "v-network-graph"
import data from "./data"
// ref="graph"
const graph = ref<vNG.Instance>()
// ref="tooltip"
const tooltip = ref<HTMLDivElement>()
// positions of the center of nodes
const layouts = ref(data.layouts)
const NODE_RADIUS = 16
const targetNodeId = ref<string>("")
const tooltipOpacity = ref(0) // 0 or 1
const tooltipPos = ref({ left: "0px", top: "0px" })
const targetNodePos = computed(() => {
const nodePos = layouts.value.nodes[targetNodeId.value]
return nodePos || { x: 0, y: 0 }
})
// Update `tooltipPos`
watch(
() => [targetNodePos.value, tooltipOpacity.value],
() => {
if (!graph.value || !tooltip.value) return
// translate coordinates: SVG -> DOM
const domPoint = graph.value.translateFromSvgToDomCoordinates(targetNodePos.value)
// calculates top-left position of the tooltip.
tooltipPos.value = {
left: domPoint.x - tooltip.value.offsetWidth / 2 + "px",
top: domPoint.y - NODE_RADIUS - tooltip.value.offsetHeight - 10 + "px",
}
},
{ deep: true }
)
const eventHandlers: vNG.EventHandlers = {
"node:pointerover": ({ node }) => {
targetNodeId.value = node
tooltipOpacity.value = 1 // show
},
"node:pointerout": _ => {
tooltipOpacity.value = 0 // hide
},
}
</script>
<template>
<div class="tooltip-wrapper">
<v-network-graph
ref="graph"
v-model:layouts="layouts"
:nodes="data.nodes"
:edges="data.edges"
:configs="data.configs"
:event-handlers="eventHandlers"
/>
<!-- Tooltip -->
<div
ref="tooltip"
class="tooltip"
:style="{ ...tooltipPos, opacity: tooltipOpacity }"
>
<div>{{ data.nodes[targetNodeId]?.name ?? "" }}</div>
</div>
</div>
</template>
<style lang="css" scoped>
.tooltip-wrapper {
position: relative;
}
.tooltip {
top: 0;
left: 0;
opacity: 0;
position: absolute;
width: 80px;
height: 36px;
display: grid;
place-content: center;
text-align: center;
font-size: 12px;
background-color: #fff0bd;
border: 1px solid #ffb950;
box-shadow: 2px 2px 2px #aaa;
transition: opacity 0.2s linear;
pointer-events: none;
}
</style>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
import { Nodes, Edges, Layouts, defineConfigs } from "v-network-graph"
const nodes: Nodes = {
node1: { name: "Node 1" },
node2: { name: "Node 2" },
node3: { name: "Node 3" },
node4: { name: "Node 4" },
}
const edges: Edges = {
edge1: { source: "node1", target: "node2" },
edge2: { source: "node2", target: "node3" },
edge3: { source: "node3", target: "node4" },
}
const layouts: Layouts = {
nodes: {
node1: { x: 0, y: 0 },
node2: { x: 80, y: 80 },
node3: { x: 160, y: 0 },
node4: { x: 240, y: 80 },
},
}
const configs = defineConfigs({
node: {
label: {
visible: false,
},
},
})
export default {
nodes,
edges,
layouts,
configs,
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
Even though there is no edge position stored in Layout
, we can still create tooltip for edges by using the node positions.
<script setup lang="ts">
import { computed, ref, watch } from "vue"
import * as vNG from "v-network-graph"
import data from "./data"
// ref="graph"
const graph = ref<vNG.Instance>()
// ref="tooltip"
const tooltip = ref<HTMLDivElement>()
// positions of the center of nodes
const layouts = ref(data.layouts)
const EDGE_MARGIN_TOP = 2
const targetEdgeId = ref("")
const tooltipOpacity = ref(0) // 0 or 1
const tooltipPos = ref({ left: "0px", top: "0px" })
const edgeCenterPos = computed(() => {
const edge = data.edges[targetEdgeId.value]
if (!edge) return { x: 0, y: 0 }
const sourceNode = data.edges[targetEdgeId.value].source
const targetNode = data.edges[targetEdgeId.value].target
return {
x: (layouts.value.nodes[sourceNode].x + layouts.value.nodes[targetNode].x) / 2,
y: (layouts.value.nodes[sourceNode].y + layouts.value.nodes[targetNode].y) / 2,
}
})
// Update `tooltipPos`
watch(
() => [edgeCenterPos.value, tooltipOpacity.value],
() => {
if (!graph.value || !tooltip.value) return { x: 0, y: 0 }
if (!targetEdgeId.value) return { x: 0, y: 0 }
// translate coordinates: SVG -> DOM
const domPoint = graph.value.translateFromSvgToDomCoordinates(edgeCenterPos.value)
// calculates top-left position of the tooltip.
tooltipPos.value = {
left: domPoint.x - tooltip.value.offsetWidth / 2 + "px",
top: domPoint.y - EDGE_MARGIN_TOP - tooltip.value.offsetHeight - 10 + "px",
}
},
{ deep: true }
)
const eventHandlers: vNG.EventHandlers = {
"edge:pointerover": ({ edge }) => {
targetEdgeId.value = edge ?? ""
tooltipOpacity.value = 1 // show
},
"edge:pointerout": _ => {
tooltipOpacity.value = 0 // hide
},
}
</script>
<template>
<div class="tooltip-wrapper">
<v-network-graph
ref="graph"
v-model:layouts="layouts"
:nodes="data.nodes"
:edges="data.edges"
:configs="data.configs"
:event-handlers="eventHandlers"
/>
<!-- Tooltip -->
<div
ref="tooltip"
class="tooltip"
:style="{ ...tooltipPos, opacity: tooltipOpacity }"
>
<div>
{{ `${data.edges[targetEdgeId]?.name ?? ""}` }}
</div>
</div>
</div>
</template>
<style lang="css" scoped>
.tooltip-wrapper {
position: relative;
}
.tooltip {
top: 0;
left: 0;
opacity: 0;
position: absolute;
width: 80px;
height: 36px;
display: grid;
place-content: center;
text-align: center;
font-size: 12px;
background-color: #fff0bd;
border: 1px solid #ffb950;
box-shadow: 2px 2px 2px #aaa;
transition: opacity 0.2s linear;
pointer-events: none;
}
</style>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
import { Nodes, Edges, Layouts, defineConfigs } from "v-network-graph"
const nodes: Nodes = {
node1: { name: "Node 1" },
node2: { name: "Node 2" },
node3: { name: "Node 3" },
node4: { name: "Node 4" },
}
const edges: Edges = {
edge1: { source: "node1", target: "node2", name: "Edge 1" },
edge2: { source: "node2", target: "node3", name: "Edge 2" },
edge3: { source: "node3", target: "node4", name: "Edge 3" },
}
const layouts: Layouts = {
nodes: {
node1: { x: 0, y: 0 },
node2: { x: 80, y: 80 },
node3: { x: 160, y: 0 },
node4: { x: 240, y: 80 },
},
}
const configs = defineConfigs({
node: {
label: {
visible: false,
},
selectable: false,
},
edge: {
normal: {
width: 5,
},
},
})
export default {
nodes,
edges,
layouts,
configs,
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
Keyboard events
v-network-graph does not support key events, but they can be obtained using the standard HTML/Vue ways.
Below is an example of deleting a selected node/edge using the keyup
event of delete
key.
<script setup lang="ts">
import { reactive, ref } from "vue"
import data from "./data"
const nodes = reactive(data.nodes)
const edges = reactive(data.edges)
const selectedNodes = ref([])
const selectedEdges = ref([])
function onDeleteKeyUp() {
if (selectedNodes.value.length > 0) {
const names = selectedNodes.value.map(n => data.nodes[n].name).join(", ")
const confirmed = confirm(`Are you sure you want to delete [${names}]?`)
if (confirmed) {
selectedNodes.value.forEach(n => delete nodes[n])
}
} else if (selectedEdges.value.length > 0) {
const ids = selectedEdges.value.join(", ")
const confirmed = confirm(`Are you sure you want to delete [${ids}]?`)
if (confirmed) {
selectedEdges.value.forEach(e => delete edges[e])
}
}
}
</script>
<template>
<!-- The `tabindex` attribute is required to fire key events. -->
<v-network-graph
tabindex="0"
:nodes="nodes"
:edges="edges"
:layouts="data.layouts"
:configs="data.configs"
v-model:selectedNodes="selectedNodes"
v-model:selectedEdges="selectedEdges"
@keyup.delete="onDeleteKeyUp"
/>
</template>
<style lang="scss" scoped>
.v-network-graph:focus {
// focus style
outline: 1px dashed #aaa;
}
</style>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
import { Nodes, Edges, Layouts, defineConfigs } from "v-network-graph"
const nodes: Nodes = {
node1: { name: "Node 1", active: false },
node2: { name: "Node 2", active: false },
node3: { name: "Node 3", active: true },
node4: { name: "Node 4", active: false },
}
const edges: Edges = {
edge1: { source: "node1", target: "node2" },
edge2: { source: "node2", target: "node3" },
edge3: { source: "node3", target: "node4" },
}
const layouts: Layouts = {
nodes: {
node1: { x: 0, y: 0 },
node2: { x: 80, y: 80 },
node3: { x: 160, y: 0 },
node4: { x: 240, y: 80 },
},
}
const configs = defineConfigs({
node: {
selectable: true,
},
edge: {
selectable: true,
},
})
export default {
nodes,
edges,
layouts,
configs,
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
Set raw event handlers to the node elements
This section shows how to set raw event handlers to a node when the event mechanism with event-handlers
is insufficient.
The handling process of mousedown/up events in event-handlers
is implemented with consideration to avoid situations where only one of node:pointerdown
and node:pointerup
can occur. This means that node:pointerup
occurs only for the node where node:pointerdown
occurs, and conversely, node:pointerup
occurs for a node where node:pointerdown
occurs even if the mouse button is released on another element in the browser.
This behavior may not be desirable, for example, if you want to be able to drag a node to specify a start point to an end point.
In such cases, it is possible to expose Node's visual elements in the following way, so please specify directly the own handler you want to set.
<script setup lang="ts">
import { reactive } from "vue"
import { VShape } from "v-network-graph"
import { format } from "date-fns/format"
import data from "./data"
const EVENTS_COUNT = 5
const eventLogs = reactive<[string, string, string][]>([])
function customEventHandler(nodeId: string, event: MouseEvent) {
const timestamp = format(new Date(), "HH:mm:ss.SSS")
if (eventLogs.length > EVENTS_COUNT) {
eventLogs.splice(EVENTS_COUNT, eventLogs.length - EVENTS_COUNT)
}
const eventInfo = {
type: event.type,
x: event.clientX,
y: event.clientY,
}
eventLogs.unshift([timestamp, nodeId, JSON.stringify(eventInfo)])
}
</script>
<template>
<v-network-graph
:nodes="data.nodes"
:edges="data.edges"
:layouts="data.layouts"
:configs="data.configs"
>
<template #override-node="slotProps">
<!-- v-shape: Internal component that draws a node shape -->
<v-shape
v-bind="slotProps"
@mousedown="customEventHandler(slotProps.nodeId, $event)"
@mouseup="customEventHandler(slotProps.nodeId, $event)"
@mouseover="customEventHandler(slotProps.nodeId, $event)"
@click="customEventHandler(slotProps.nodeId, $event)"
@dblclick="customEventHandler(slotProps.nodeId, $event)"
/>
</template>
</v-network-graph>
<div v-if="eventLogs.length > 0" class="event-logs">
<div
v-for="[timestamp, nodeId, event] in eventLogs"
:key="`${timestamp}/${nodeId}/${event}`"
>
{{ timestamp }}
[{{ nodeId }} ({{ data.nodes[nodeId].name }})]
{{ event }}
</div>
</div>
</template>
<style lang="css" scoped>
.event-logs {
position: absolute;
inset: auto 10px 10px auto;
margin-left: 10px;
padding: 10px;
background: #ffff0044;
border-radius: 4px;
font-size: 11px;
font-family: monospace;
line-height: 11px;
pointer-events: none;
}
.event-logs div {
word-break: break-all;
}
</style>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
import { Nodes, Edges, Layouts, defineConfigs } from "v-network-graph"
const nodes: Nodes = {
node1: { name: "N1" },
node2: { name: "N2" },
node3: { name: "N3" },
}
const edges: Edges = {
edge1: { source: "node1", target: "node2" },
edge2: { source: "node2", target: "node3" },
edge3: { source: "node3", target: "node1" },
}
const layouts: Layouts = {
nodes: {
node1: { x: 50, y: 0 },
node2: { x: 0, y: 75 },
node3: { x: 100, y: 75 },
},
}
const configs = defineConfigs({
view: {
panEnabled: false,
zoomEnabled: false,
doubleClickZoomEnabled: false,
},
node: {
draggable: false,
},
})
export default {
nodes,
edges,
layouts,
configs,
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39