feat(docs): add shuffle to layout example

This commit is contained in:
braks
2024-02-08 21:54:50 +01:00
committed by Braks
parent c65f5cf56e
commit a0abe3af9d
5 changed files with 121 additions and 21 deletions

View File

@@ -18,7 +18,7 @@ import { IntersectionApp, IntersectionCSS } from './intersection'
import { SnapToHandleApp, SnappableConnectionLine } from './connection-radius'
import { NodeResizerApp, ResizableNode } from './node-resizer'
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 = {
basic: {
@@ -129,7 +129,9 @@ export const exampleImports = {
'initial-elements.js': LayoutElements,
'ProcessNode.vue': LayoutNode,
'AnimationEdge.vue': LayoutEdge,
'useRunProcess.js': LayoutScript,
'useRunProcess.js': useRunProcess,
'useShuffle.js': useShuffle,
'Icon.vue': LayoutIcon,
'additionalImports': {
'@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',

View File

@@ -3,11 +3,13 @@ import dagre from 'dagre'
import { nextTick, ref } from 'vue'
import { Panel, Position, VueFlow, useVueFlow } from '@vue-flow/core'
import { Background } from '@vue-flow/background'
import Icon from './Icon.vue'
import ProcessNode from './ProcessNode.vue'
import AnimationEdge from './AnimationEdge.vue'
import { initialEdges, initialNodes } from './initial-elements.js'
import { useRunProcess } from './useRunProcess'
import { useShuffle } from './useShuffle'
const nodes = ref(initialNodes)
@@ -17,7 +19,9 @@ const dagreGraph = ref(new dagre.graphlib.Graph())
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()
@@ -37,6 +41,7 @@ function handleLayout(direction) {
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) {
dagreGraph.value.setEdge(edge.source, edge.target)
}
@@ -59,6 +64,16 @@ function handleLayout(direction) {
fitView()
})
}
function shuffleGraph() {
reset(nodes.value)
edges.value = shuffle(nodes.value)
nextTick(() => {
handleLayout('LR')
})
}
</script>
<template>
@@ -86,26 +101,23 @@ function handleLayout(direction) {
<Panel class="process-panel" position="top-right">
<div class="layout-panel">
<button v-if="isRunning" @click="stop">🛑</button>
<button v-else @click="run(nodes)">
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path d="M8 5v14l11-7z" fill="currentColor" />
</svg>
<button v-if="isRunning" title="stop" @click="stop">
<Icon name="stop" />
</button>
<button v-else title="start" @click="run(nodes)">
<Icon name="play" />
</button>
<button title="horizontal" @click="handleLayout('LR')">
<svg 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>
<button title="set horizontal layout" @click="handleLayout('LR')">
<Icon name="horizontal" />
</button>
<button title="vertical" @click="handleLayout('TB')">
<svg 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>
<button title="set vertical layout" @click="handleLayout('TB')">
<Icon name="vertical" />
</button>
<button title="shuffle graph" @click="shuffleGraph">
<Icon name="shuffle" />
</button>
</div>

View File

@@ -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>

View File

@@ -2,4 +2,6 @@ export { default as LayoutApp } from './App.vue?raw'
export { default as LayoutElements } from './initial-elements.js?raw'
export { default as LayoutNode } from './ProcessNode.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'

View File

@@ -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
}
}