mirror of
https://github.com/lana-k/sqliteviz.git
synced 2026-05-06 20:09:18 +08:00
Support circle pack as initial algorithm #136
This commit is contained in:
@@ -9,16 +9,13 @@
|
||||
/>
|
||||
</Field>
|
||||
|
||||
<Field
|
||||
v-if="modelValue.initialAlgorithm === 'random'"
|
||||
label="Seed value"
|
||||
fieldContainerClassName="test_fa2_seed_value"
|
||||
>
|
||||
<NumericInput
|
||||
:value="modelValue.seedValue"
|
||||
@update="update('seedValue', $event)"
|
||||
/>
|
||||
</Field>
|
||||
<component
|
||||
:is="layoutSettingsComponentMap[modelValue.initialAlgorithm]"
|
||||
v-if="modelValue.initialAlgorithm !== 'circular'"
|
||||
:model-value="modelValue"
|
||||
:keyOptions="keyOptions"
|
||||
@update:model-value="this.$emit('update:modelValue', $event)"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
@@ -28,12 +25,16 @@ import Field from 'react-chart-editor/lib/components/fields/Field'
|
||||
import NumericInput from 'react-chart-editor/lib/components/widgets/NumericInput'
|
||||
import Dropdown from 'react-chart-editor/lib/components/widgets/Dropdown'
|
||||
import 'react-chart-editor/lib/react-chart-editor.css'
|
||||
import CirclePackLayoutSettings from '@/components/Graph/CirclePackLayoutSettings.vue'
|
||||
import RandomLayoutSettings from '@/components/Graph/RandomLayoutSettings.vue'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
Field: applyPureReactInVue(Field),
|
||||
Dropdown: applyPureReactInVue(Dropdown),
|
||||
NumericInput: applyPureReactInVue(NumericInput)
|
||||
NumericInput: applyPureReactInVue(NumericInput),
|
||||
RandomLayoutSettings,
|
||||
CirclePackLayoutSettings
|
||||
},
|
||||
props: {
|
||||
modelValue: Object,
|
||||
@@ -44,8 +45,13 @@ export default {
|
||||
return {
|
||||
layoutOptions: markRaw([
|
||||
{ label: 'Circular', value: 'circular' },
|
||||
{ label: 'Random', value: 'random' }
|
||||
])
|
||||
{ label: 'Random', value: 'random' },
|
||||
{ label: 'Circle pack', value: 'circlepack' }
|
||||
]),
|
||||
layoutSettingsComponentMap: markRaw({
|
||||
random: RandomLayoutSettings,
|
||||
circlepack: CirclePackLayoutSettings
|
||||
})
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
||||
@@ -337,6 +337,12 @@ export default {
|
||||
circlepack: CirclePackLayoutSettings,
|
||||
forceAtlas2: ForceAtlasLayoutSettings
|
||||
}),
|
||||
layoutMethodMap: markRaw({
|
||||
circular: this.applyCircularLayout,
|
||||
random: this.applyRandomLayout,
|
||||
circlepack: this.applyCirclePackLayout,
|
||||
forceAtlas2: this.applyFA2Layout
|
||||
}),
|
||||
selectedNodeId: undefined,
|
||||
hoveredNodeId: undefined,
|
||||
selectedEdgeId: undefined,
|
||||
@@ -668,54 +674,10 @@ export default {
|
||||
this.fa2Layout.kill()
|
||||
}
|
||||
|
||||
if (layoutType === 'circular') {
|
||||
this.applyCircularLayout()
|
||||
return
|
||||
}
|
||||
this.layoutMethodMap[layoutType]()
|
||||
|
||||
if (layoutType === 'random') {
|
||||
this.applyRandomLayout()
|
||||
return
|
||||
}
|
||||
|
||||
if (layoutType === 'circlepack') {
|
||||
this.graph.forEachNode(nodeId => {
|
||||
this.graph.updateNode(nodeId, attributes => {
|
||||
const newAttributes = { ...attributes }
|
||||
// Delete old hierarchy attributes
|
||||
Object.keys(newAttributes)
|
||||
.filter(key => key.startsWith('hierarchyAttribute'))
|
||||
.forEach(
|
||||
hierarchyAttributeKey =>
|
||||
delete newAttributes[hierarchyAttributeKey]
|
||||
)
|
||||
// Set new hierarchy attributes
|
||||
this.settings.layout.options.hierarchyAttributes?.forEach(
|
||||
(hierarchyAttribute, index) => {
|
||||
newAttributes['hierarchyAttribute' + index] =
|
||||
attributes.data[hierarchyAttribute]
|
||||
}
|
||||
)
|
||||
|
||||
return newAttributes
|
||||
})
|
||||
})
|
||||
|
||||
circlepack.assign(this.graph, {
|
||||
hierarchyAttributes:
|
||||
this.settings.layout.options.hierarchyAttributes?.map(
|
||||
(_, index) => 'hierarchyAttribute' + index
|
||||
) || [],
|
||||
rng: seedrandom(this.settings.layout.options.seedValue)
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
if (layoutType === 'forceAtlas2') {
|
||||
this.applyFA2Layout()
|
||||
if (layoutType !== prevLayout) {
|
||||
this.autoRunFA2Layout()
|
||||
}
|
||||
if (layoutType === 'forceAtlas2' && layoutType !== prevLayout) {
|
||||
this.autoRunFA2Layout()
|
||||
}
|
||||
},
|
||||
applyCircularLayout() {
|
||||
@@ -726,6 +688,37 @@ export default {
|
||||
rng: seedrandom(this.settings.layout.options.seedValue)
|
||||
})
|
||||
},
|
||||
applyCirclePackLayout() {
|
||||
this.graph.forEachNode(nodeId => {
|
||||
this.graph.updateNode(nodeId, attributes => {
|
||||
const newAttributes = { ...attributes }
|
||||
// Delete old hierarchy attributes
|
||||
Object.keys(newAttributes)
|
||||
.filter(key => key.startsWith('hierarchyAttribute'))
|
||||
.forEach(
|
||||
hierarchyAttributeKey =>
|
||||
delete newAttributes[hierarchyAttributeKey]
|
||||
)
|
||||
// Set new hierarchy attributes
|
||||
this.settings.layout.options.hierarchyAttributes?.forEach(
|
||||
(hierarchyAttribute, index) => {
|
||||
newAttributes['hierarchyAttribute' + index] =
|
||||
attributes.data[hierarchyAttribute]
|
||||
}
|
||||
)
|
||||
|
||||
return newAttributes
|
||||
})
|
||||
})
|
||||
|
||||
circlepack.assign(this.graph, {
|
||||
hierarchyAttributes:
|
||||
this.settings.layout.options.hierarchyAttributes?.map(
|
||||
(_, index) => 'hierarchyAttribute' + index
|
||||
) || [],
|
||||
rng: seedrandom(this.settings.layout.options.seedValue)
|
||||
})
|
||||
},
|
||||
applyFA2Layout() {
|
||||
if (
|
||||
!this.graph.someNode(
|
||||
@@ -733,20 +726,22 @@ export default {
|
||||
typeof attributes.x === 'number' && typeof attributes.y === 'number'
|
||||
)
|
||||
) {
|
||||
if (this.settings.layout.options.initialAlgorithm === 'circular') {
|
||||
this.applyCircularLayout()
|
||||
} else {
|
||||
this.applyRandomLayout()
|
||||
}
|
||||
this.layoutMethodMap[this.settings.layout.options.initialAlgorithm]()
|
||||
}
|
||||
|
||||
const fa2settings = { ...this.settings.layout.options }
|
||||
// delete all custom settings because they can break the algorithm running
|
||||
delete fa2settings.initialAlgorithm
|
||||
delete fa2settings.seedValue
|
||||
delete fa2settings.initialIterationsAmount
|
||||
delete fa2settings.hierarchyAttributes
|
||||
this.fa2Layout = markRaw(
|
||||
new FA2Layout(this.graph, {
|
||||
getEdgeWeight: (_, attr) =>
|
||||
this.settings.layout.options.weightSource
|
||||
? attr.data[this.settings.layout.options.weightSource]
|
||||
: 1,
|
||||
settings: this.settings.layout.options
|
||||
settings: fa2settings
|
||||
})
|
||||
)
|
||||
},
|
||||
@@ -773,6 +768,7 @@ export default {
|
||||
if (this.fa2Layout.isRunning()) {
|
||||
this.stopFA2Layout()
|
||||
}
|
||||
this.fa2Layout.kill()
|
||||
clearNodeCoordinates(this.graph)
|
||||
this.applyFA2Layout()
|
||||
this.autoRunFA2Layout()
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<Field label="Seed value">
|
||||
<Field label="Seed value" fieldContainerClassName="test_seed_value">
|
||||
<NumericInput
|
||||
:value="modelValue.seedValue"
|
||||
@update="update('seedValue', $event)"
|
||||
|
||||
@@ -38,8 +38,8 @@ export function dataSourceIsValid(dataSources) {
|
||||
|
||||
export function clearNodeCoordinates(graph) {
|
||||
graph.forEachNode((nodeId, attributes) => {
|
||||
delete attributes.x
|
||||
delete attributes.y
|
||||
attributes.x = undefined
|
||||
attributes.y = undefined
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user