feat(docs): add shuffle to layout example
This commit is contained in:
@@ -18,7 +18,7 @@ import { IntersectionApp, IntersectionCSS } from './intersection'
|
|||||||
import { SnapToHandleApp, SnappableConnectionLine } from './connection-radius'
|
import { SnapToHandleApp, SnappableConnectionLine } from './connection-radius'
|
||||||
import { NodeResizerApp, ResizableNode } from './node-resizer'
|
import { NodeResizerApp, ResizableNode } from './node-resizer'
|
||||||
import { ToolbarApp, ToolbarNode } from './node-toolbar'
|
import { ToolbarApp, ToolbarNode } from './node-toolbar'
|
||||||
import { LayoutApp, LayoutEdge, LayoutElements, LayoutNode, LayoutScript } from './layout'
|
import { LayoutApp, LayoutEdge, LayoutElements, LayoutIcon, LayoutNode, useRunProcess, useShuffle } from './layout'
|
||||||
|
|
||||||
export const exampleImports = {
|
export const exampleImports = {
|
||||||
basic: {
|
basic: {
|
||||||
@@ -129,7 +129,9 @@ export const exampleImports = {
|
|||||||
'initial-elements.js': LayoutElements,
|
'initial-elements.js': LayoutElements,
|
||||||
'ProcessNode.vue': LayoutNode,
|
'ProcessNode.vue': LayoutNode,
|
||||||
'AnimationEdge.vue': LayoutEdge,
|
'AnimationEdge.vue': LayoutEdge,
|
||||||
'useRunProcess.js': LayoutScript,
|
'useRunProcess.js': useRunProcess,
|
||||||
|
'useShuffle.js': useShuffle,
|
||||||
|
'Icon.vue': LayoutIcon,
|
||||||
'additionalImports': {
|
'additionalImports': {
|
||||||
'@vueuse/core': 'https://cdn.jsdelivr.net/npm/@vueuse/core@10.7.0/index.mjs',
|
'@vueuse/core': 'https://cdn.jsdelivr.net/npm/@vueuse/core@10.7.0/index.mjs',
|
||||||
'@vueuse/shared': 'https://cdn.jsdelivr.net/npm/@vueuse/shared@10.7.0/index.mjs',
|
'@vueuse/shared': 'https://cdn.jsdelivr.net/npm/@vueuse/shared@10.7.0/index.mjs',
|
||||||
|
|||||||
@@ -3,11 +3,13 @@ import dagre from 'dagre'
|
|||||||
import { nextTick, ref } from 'vue'
|
import { nextTick, ref } from 'vue'
|
||||||
import { Panel, Position, VueFlow, useVueFlow } from '@vue-flow/core'
|
import { Panel, Position, VueFlow, useVueFlow } from '@vue-flow/core'
|
||||||
import { Background } from '@vue-flow/background'
|
import { Background } from '@vue-flow/background'
|
||||||
|
import Icon from './Icon.vue'
|
||||||
import ProcessNode from './ProcessNode.vue'
|
import ProcessNode from './ProcessNode.vue'
|
||||||
import AnimationEdge from './AnimationEdge.vue'
|
import AnimationEdge from './AnimationEdge.vue'
|
||||||
|
|
||||||
import { initialEdges, initialNodes } from './initial-elements.js'
|
import { initialEdges, initialNodes } from './initial-elements.js'
|
||||||
import { useRunProcess } from './useRunProcess'
|
import { useRunProcess } from './useRunProcess'
|
||||||
|
import { useShuffle } from './useShuffle'
|
||||||
|
|
||||||
const nodes = ref(initialNodes)
|
const nodes = ref(initialNodes)
|
||||||
|
|
||||||
@@ -17,7 +19,9 @@ const dagreGraph = ref(new dagre.graphlib.Graph())
|
|||||||
|
|
||||||
const cancelOnError = ref(true)
|
const cancelOnError = ref(true)
|
||||||
|
|
||||||
const { run, stop, isRunning } = useRunProcess({ dagreGraph, cancelOnError })
|
const shuffle = useShuffle()
|
||||||
|
|
||||||
|
const { run, stop, reset, isRunning } = useRunProcess({ dagreGraph, cancelOnError })
|
||||||
|
|
||||||
const { findNode, fitView } = useVueFlow()
|
const { findNode, fitView } = useVueFlow()
|
||||||
|
|
||||||
@@ -37,6 +41,7 @@ function handleLayout(direction) {
|
|||||||
dagreGraph.value.setNode(node.id, { width: graphNode.dimensions.width || 150, height: graphNode.dimensions.height || 50 })
|
dagreGraph.value.setNode(node.id, { width: graphNode.dimensions.width || 150, height: graphNode.dimensions.height || 50 })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
console.log(edges.value)
|
||||||
for (const edge of edges.value) {
|
for (const edge of edges.value) {
|
||||||
dagreGraph.value.setEdge(edge.source, edge.target)
|
dagreGraph.value.setEdge(edge.source, edge.target)
|
||||||
}
|
}
|
||||||
@@ -59,6 +64,16 @@ function handleLayout(direction) {
|
|||||||
fitView()
|
fitView()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function shuffleGraph() {
|
||||||
|
reset(nodes.value)
|
||||||
|
|
||||||
|
edges.value = shuffle(nodes.value)
|
||||||
|
|
||||||
|
nextTick(() => {
|
||||||
|
handleLayout('LR')
|
||||||
|
})
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@@ -86,26 +101,23 @@ function handleLayout(direction) {
|
|||||||
|
|
||||||
<Panel class="process-panel" position="top-right">
|
<Panel class="process-panel" position="top-right">
|
||||||
<div class="layout-panel">
|
<div class="layout-panel">
|
||||||
<button v-if="isRunning" @click="stop">🛑</button>
|
<button v-if="isRunning" title="stop" @click="stop">
|
||||||
<button v-else @click="run(nodes)">
|
<Icon name="stop" />
|
||||||
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
</button>
|
||||||
<path d="M8 5v14l11-7z" fill="currentColor" />
|
<button v-else title="start" @click="run(nodes)">
|
||||||
</svg>
|
<Icon name="play" />
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<button title="horizontal" @click="handleLayout('LR')">
|
<button title="set horizontal layout" @click="handleLayout('LR')">
|
||||||
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
<Icon name="horizontal" />
|
||||||
<path d="M2,12 L22,12" stroke="currentColor" stroke-width="2" />
|
|
||||||
<path d="M7,7 L2,12 L7,17" stroke="currentColor" stroke-width="2" fill="none" />
|
|
||||||
<path d="M17,7 L22,12 L17,17" stroke="currentColor" stroke-width="2" fill="none" />
|
|
||||||
</svg>
|
|
||||||
</button>
|
</button>
|
||||||
<button title="vertical" @click="handleLayout('TB')">
|
|
||||||
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
<button title="set vertical layout" @click="handleLayout('TB')">
|
||||||
<path d="M12,2 L12,22" stroke="currentColor" stroke-width="2" />
|
<Icon name="vertical" />
|
||||||
<path d="M7,7 L12,2 L17,7" stroke="currentColor" stroke-width="2" fill="none" />
|
</button>
|
||||||
<path d="M7,17 L12,22 L17,17" stroke="currentColor" stroke-width="2" fill="none" />
|
|
||||||
</svg>
|
<button title="shuffle graph" @click="shuffleGraph">
|
||||||
|
<Icon name="shuffle" />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,40 @@
|
|||||||
|
<script setup>
|
||||||
|
defineProps({
|
||||||
|
name: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<svg v-if="name === 'play'" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M8 5v14l11-7z" fill="currentColor" />
|
||||||
|
</svg>
|
||||||
|
|
||||||
|
<svg v-else-if="name === 'stop'" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
||||||
|
<path
|
||||||
|
fill="currentColor"
|
||||||
|
d="M8 16h8V8H8zm4 6q-2.075 0-3.9-.788t-3.175-2.137q-1.35-1.35-2.137-3.175T2 12q0-2.075.788-3.9t2.137-3.175q1.35-1.35 3.175-2.137T12 2q2.075 0 3.9.788t3.175 2.137q1.35 1.35 2.138 3.175T22 12q0 2.075-.788 3.9t-2.137 3.175q-1.35 1.35-3.175 2.138T12 22"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
|
||||||
|
<svg v-else-if="name === 'horizontal'" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M2,12 L22,12" stroke="currentColor" stroke-width="2" />
|
||||||
|
<path d="M7,7 L2,12 L7,17" stroke="currentColor" stroke-width="2" fill="none" />
|
||||||
|
<path d="M17,7 L22,12 L17,17" stroke="currentColor" stroke-width="2" fill="none" />
|
||||||
|
</svg>
|
||||||
|
|
||||||
|
<svg v-else-if="name === 'vertical'" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M12,2 L12,22" stroke="currentColor" stroke-width="2" />
|
||||||
|
<path d="M7,7 L12,2 L17,7" stroke="currentColor" stroke-width="2" fill="none" />
|
||||||
|
<path d="M7,17 L12,22 L17,17" stroke="currentColor" stroke-width="2" fill="none" />
|
||||||
|
</svg>
|
||||||
|
|
||||||
|
<svg v-else-if="name === 'shuffle'" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
||||||
|
<path
|
||||||
|
fill="currentColor"
|
||||||
|
d="M14 20v-2h2.6l-3.175-3.175L14.85 13.4L18 16.55V14h2v6zm-8.6 0L4 18.6L16.6 6H14V4h6v6h-2V7.4zm3.775-9.425L4 5.4L5.4 4l5.175 5.175z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</template>
|
||||||
@@ -2,4 +2,6 @@ export { default as LayoutApp } from './App.vue?raw'
|
|||||||
export { default as LayoutElements } from './initial-elements.js?raw'
|
export { default as LayoutElements } from './initial-elements.js?raw'
|
||||||
export { default as LayoutNode } from './ProcessNode.vue?raw'
|
export { default as LayoutNode } from './ProcessNode.vue?raw'
|
||||||
export { default as LayoutEdge } from './AnimationEdge.vue?raw'
|
export { default as LayoutEdge } from './AnimationEdge.vue?raw'
|
||||||
export { default as LayoutScript } from './useRunProcess.js?raw'
|
export { default as useRunProcess } from './useRunProcess.js?raw'
|
||||||
|
export { default as useShuffle } from './useShuffle.js?raw'
|
||||||
|
export { default as LayoutIcon } from './Icon.vue?raw'
|
||||||
|
|||||||
@@ -0,0 +1,44 @@
|
|||||||
|
function shuffleArray(array) {
|
||||||
|
for (let i = array.length - 1; i > 0; i--) {
|
||||||
|
const j = Math.floor(Math.random() * (i + 1))
|
||||||
|
;[array[i], array[j]] = [array[j], array[i]]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// generate a list of all possible edges, excluding duplicates and self-references
|
||||||
|
function generatePossibleEdges(nodes) {
|
||||||
|
const possibleEdges = []
|
||||||
|
|
||||||
|
for (const sourceNode of nodes) {
|
||||||
|
for (const targetNode of nodes) {
|
||||||
|
if (sourceNode.id !== targetNode.id) {
|
||||||
|
const edgeId = `e${sourceNode.id}-${targetNode.id}`
|
||||||
|
possibleEdges.push({ id: edgeId, source: sourceNode.id, target: targetNode.id, type: 'animation', animated: true })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return possibleEdges
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function to create a new shuffled edges array
|
||||||
|
export function useShuffle() {
|
||||||
|
return (nodes) => {
|
||||||
|
const possibleEdges = generatePossibleEdges(nodes)
|
||||||
|
shuffleArray(possibleEdges)
|
||||||
|
|
||||||
|
const usedNodes = new Set()
|
||||||
|
const newEdges = []
|
||||||
|
|
||||||
|
// ensure every node is used, maintaining a single starting node and no duplicate connections
|
||||||
|
for (const edge of possibleEdges) {
|
||||||
|
if (!usedNodes.has(edge.target) && (usedNodes.size === 0 || usedNodes.has(edge.source))) {
|
||||||
|
newEdges.push(edge)
|
||||||
|
usedNodes.add(edge.source)
|
||||||
|
usedNodes.add(edge.target)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return newEdges
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user