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>
|
||||||
|
|
||||||
<Field
|
<component
|
||||||
v-if="modelValue.initialAlgorithm === 'random'"
|
:is="layoutSettingsComponentMap[modelValue.initialAlgorithm]"
|
||||||
label="Seed value"
|
v-if="modelValue.initialAlgorithm !== 'circular'"
|
||||||
fieldContainerClassName="test_fa2_seed_value"
|
:model-value="modelValue"
|
||||||
>
|
:keyOptions="keyOptions"
|
||||||
<NumericInput
|
@update:model-value="this.$emit('update:modelValue', $event)"
|
||||||
:value="modelValue.seedValue"
|
|
||||||
@update="update('seedValue', $event)"
|
|
||||||
/>
|
/>
|
||||||
</Field>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<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 NumericInput from 'react-chart-editor/lib/components/widgets/NumericInput'
|
||||||
import Dropdown from 'react-chart-editor/lib/components/widgets/Dropdown'
|
import Dropdown from 'react-chart-editor/lib/components/widgets/Dropdown'
|
||||||
import 'react-chart-editor/lib/react-chart-editor.css'
|
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 {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
Field: applyPureReactInVue(Field),
|
Field: applyPureReactInVue(Field),
|
||||||
Dropdown: applyPureReactInVue(Dropdown),
|
Dropdown: applyPureReactInVue(Dropdown),
|
||||||
NumericInput: applyPureReactInVue(NumericInput)
|
NumericInput: applyPureReactInVue(NumericInput),
|
||||||
|
RandomLayoutSettings,
|
||||||
|
CirclePackLayoutSettings
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
modelValue: Object,
|
modelValue: Object,
|
||||||
@@ -44,8 +45,13 @@ export default {
|
|||||||
return {
|
return {
|
||||||
layoutOptions: markRaw([
|
layoutOptions: markRaw([
|
||||||
{ label: 'Circular', value: 'circular' },
|
{ label: 'Circular', value: 'circular' },
|
||||||
{ label: 'Random', value: 'random' }
|
{ label: 'Random', value: 'random' },
|
||||||
])
|
{ label: 'Circle pack', value: 'circlepack' }
|
||||||
|
]),
|
||||||
|
layoutSettingsComponentMap: markRaw({
|
||||||
|
random: RandomLayoutSettings,
|
||||||
|
circlepack: CirclePackLayoutSettings
|
||||||
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
|||||||
@@ -337,6 +337,12 @@ export default {
|
|||||||
circlepack: CirclePackLayoutSettings,
|
circlepack: CirclePackLayoutSettings,
|
||||||
forceAtlas2: ForceAtlasLayoutSettings
|
forceAtlas2: ForceAtlasLayoutSettings
|
||||||
}),
|
}),
|
||||||
|
layoutMethodMap: markRaw({
|
||||||
|
circular: this.applyCircularLayout,
|
||||||
|
random: this.applyRandomLayout,
|
||||||
|
circlepack: this.applyCirclePackLayout,
|
||||||
|
forceAtlas2: this.applyFA2Layout
|
||||||
|
}),
|
||||||
selectedNodeId: undefined,
|
selectedNodeId: undefined,
|
||||||
hoveredNodeId: undefined,
|
hoveredNodeId: undefined,
|
||||||
selectedEdgeId: undefined,
|
selectedEdgeId: undefined,
|
||||||
@@ -668,17 +674,21 @@ export default {
|
|||||||
this.fa2Layout.kill()
|
this.fa2Layout.kill()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (layoutType === 'circular') {
|
this.layoutMethodMap[layoutType]()
|
||||||
this.applyCircularLayout()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if (layoutType === 'random') {
|
if (layoutType === 'forceAtlas2' && layoutType !== prevLayout) {
|
||||||
this.applyRandomLayout()
|
this.autoRunFA2Layout()
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
},
|
||||||
if (layoutType === 'circlepack') {
|
applyCircularLayout() {
|
||||||
|
circular.assign(this.graph)
|
||||||
|
},
|
||||||
|
applyRandomLayout() {
|
||||||
|
random.assign(this.graph, {
|
||||||
|
rng: seedrandom(this.settings.layout.options.seedValue)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
applyCirclePackLayout() {
|
||||||
this.graph.forEachNode(nodeId => {
|
this.graph.forEachNode(nodeId => {
|
||||||
this.graph.updateNode(nodeId, attributes => {
|
this.graph.updateNode(nodeId, attributes => {
|
||||||
const newAttributes = { ...attributes }
|
const newAttributes = { ...attributes }
|
||||||
@@ -708,23 +718,6 @@ export default {
|
|||||||
) || [],
|
) || [],
|
||||||
rng: seedrandom(this.settings.layout.options.seedValue)
|
rng: seedrandom(this.settings.layout.options.seedValue)
|
||||||
})
|
})
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if (layoutType === 'forceAtlas2') {
|
|
||||||
this.applyFA2Layout()
|
|
||||||
if (layoutType !== prevLayout) {
|
|
||||||
this.autoRunFA2Layout()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
applyCircularLayout() {
|
|
||||||
circular.assign(this.graph)
|
|
||||||
},
|
|
||||||
applyRandomLayout() {
|
|
||||||
random.assign(this.graph, {
|
|
||||||
rng: seedrandom(this.settings.layout.options.seedValue)
|
|
||||||
})
|
|
||||||
},
|
},
|
||||||
applyFA2Layout() {
|
applyFA2Layout() {
|
||||||
if (
|
if (
|
||||||
@@ -733,20 +726,22 @@ export default {
|
|||||||
typeof attributes.x === 'number' && typeof attributes.y === 'number'
|
typeof attributes.x === 'number' && typeof attributes.y === 'number'
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
if (this.settings.layout.options.initialAlgorithm === 'circular') {
|
this.layoutMethodMap[this.settings.layout.options.initialAlgorithm]()
|
||||||
this.applyCircularLayout()
|
|
||||||
} else {
|
|
||||||
this.applyRandomLayout()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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(
|
this.fa2Layout = markRaw(
|
||||||
new FA2Layout(this.graph, {
|
new FA2Layout(this.graph, {
|
||||||
getEdgeWeight: (_, attr) =>
|
getEdgeWeight: (_, attr) =>
|
||||||
this.settings.layout.options.weightSource
|
this.settings.layout.options.weightSource
|
||||||
? attr.data[this.settings.layout.options.weightSource]
|
? attr.data[this.settings.layout.options.weightSource]
|
||||||
: 1,
|
: 1,
|
||||||
settings: this.settings.layout.options
|
settings: fa2settings
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
@@ -773,6 +768,7 @@ export default {
|
|||||||
if (this.fa2Layout.isRunning()) {
|
if (this.fa2Layout.isRunning()) {
|
||||||
this.stopFA2Layout()
|
this.stopFA2Layout()
|
||||||
}
|
}
|
||||||
|
this.fa2Layout.kill()
|
||||||
clearNodeCoordinates(this.graph)
|
clearNodeCoordinates(this.graph)
|
||||||
this.applyFA2Layout()
|
this.applyFA2Layout()
|
||||||
this.autoRunFA2Layout()
|
this.autoRunFA2Layout()
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<Field label="Seed value">
|
<Field label="Seed value" fieldContainerClassName="test_seed_value">
|
||||||
<NumericInput
|
<NumericInput
|
||||||
:value="modelValue.seedValue"
|
:value="modelValue.seedValue"
|
||||||
@update="update('seedValue', $event)"
|
@update="update('seedValue', $event)"
|
||||||
|
|||||||
@@ -38,8 +38,8 @@ export function dataSourceIsValid(dataSources) {
|
|||||||
|
|
||||||
export function clearNodeCoordinates(graph) {
|
export function clearNodeCoordinates(graph) {
|
||||||
graph.forEachNode((nodeId, attributes) => {
|
graph.forEachNode((nodeId, attributes) => {
|
||||||
delete attributes.x
|
attributes.x = undefined
|
||||||
delete attributes.y
|
attributes.y = undefined
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1423,7 +1423,7 @@ describe('GraphEditor', () => {
|
|||||||
)
|
)
|
||||||
|
|
||||||
// Change seed value
|
// Change seed value
|
||||||
const seedValueInput = wrapper.find('.test_fa2_seed_value input')
|
const seedValueInput = wrapper.find('.test_seed_value input')
|
||||||
await seedValueInput.setValue(123)
|
await seedValueInput.setValue(123)
|
||||||
seedValueInput.wrapperElement.dispatchEvent(
|
seedValueInput.wrapperElement.dispatchEvent(
|
||||||
new Event('blur', { bubbles: true })
|
new Event('blur', { bubbles: true })
|
||||||
@@ -1659,7 +1659,7 @@ describe('GraphEditor', () => {
|
|||||||
.join()
|
.join()
|
||||||
|
|
||||||
// Change seed value
|
// Change seed value
|
||||||
const seedValueInput = wrapper.find('.test_fa2_seed_value input')
|
const seedValueInput = wrapper.find('.test_seed_value input')
|
||||||
await seedValueInput.setValue(123)
|
await seedValueInput.setValue(123)
|
||||||
seedValueInput.wrapperElement.dispatchEvent(
|
seedValueInput.wrapperElement.dispatchEvent(
|
||||||
new Event('blur', { bubbles: true })
|
new Event('blur', { bubbles: true })
|
||||||
@@ -1787,7 +1787,7 @@ describe('GraphEditor', () => {
|
|||||||
await nextTick()
|
await nextTick()
|
||||||
|
|
||||||
// Change seed value
|
// Change seed value
|
||||||
const seedValueInput = wrapper.find('.test_fa2_seed_value input')
|
const seedValueInput = wrapper.find('.test_seed_value input')
|
||||||
await seedValueInput.setValue(123)
|
await seedValueInput.setValue(123)
|
||||||
seedValueInput.wrapperElement.dispatchEvent(
|
seedValueInput.wrapperElement.dispatchEvent(
|
||||||
new Event('blur', { bubbles: true })
|
new Event('blur', { bubbles: true })
|
||||||
|
|||||||
Reference in New Issue
Block a user