Improved interface for map view
This commit is contained in:
@@ -77,8 +77,9 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Handle type="target" :position="Position.Left" class="handle-left" />
|
||||
<Handle type="source" :position="Position.Right" class="handle-right" />
|
||||
<!-- Center connection handles - no position specified for true center -->
|
||||
<Handle type="source" class="handle-center" />
|
||||
<Handle type="target" class="handle-center" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -190,11 +191,12 @@ function cancelContentEdit() {
|
||||
box-shadow: 0 0 0 2px #3b82f6;
|
||||
}
|
||||
|
||||
.handle-left,
|
||||
.handle-right {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
border: 2px solid #3b82f6;
|
||||
background: white;
|
||||
.handle-center {
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
</style>
|
||||
@@ -134,6 +134,16 @@ function exportFile() {
|
||||
border: none;
|
||||
}
|
||||
|
||||
.vue-flow__edge.vue-flow__edge-straight {
|
||||
stroke: #64748b;
|
||||
stroke-width: 2;
|
||||
}
|
||||
|
||||
.vue-flow__edge.vue-flow__edge-straight:hover {
|
||||
stroke: #3b82f6;
|
||||
stroke-width: 3;
|
||||
}
|
||||
|
||||
.vue-flow__edge.vue-flow__edge-smoothstep {
|
||||
stroke: #64748b;
|
||||
stroke-width: 2;
|
||||
|
||||
@@ -14,7 +14,9 @@ export interface FlowEdge {
|
||||
id: string
|
||||
source: string
|
||||
target: string
|
||||
type: 'smoothstep'
|
||||
sourceHandle?: string
|
||||
targetHandle?: string
|
||||
type: 'straight' | 'smoothstep'
|
||||
}
|
||||
|
||||
export function generateNodeLayout(nodes: OrgNode[]): { nodes: FlowNode[]; edges: FlowEdge[] } {
|
||||
@@ -22,63 +24,80 @@ export function generateNodeLayout(nodes: OrgNode[]): { nodes: FlowNode[]; edges
|
||||
const flowEdges: FlowEdge[] = []
|
||||
|
||||
let nodeCounter = 0
|
||||
const levelPositions: Map<number, number> = new Map() // Track position within each level
|
||||
|
||||
function processNode(
|
||||
node: OrgNode,
|
||||
level: number,
|
||||
parentId: string | null,
|
||||
angle: number,
|
||||
distance: number,
|
||||
centerX: number = 400,
|
||||
centerY: number = 300
|
||||
) {
|
||||
parentX: number = 400,
|
||||
parentY: number = 100
|
||||
): string {
|
||||
const nodeId = `node-${nodeCounter++}`
|
||||
|
||||
// Calculate position in a radial/organic layout
|
||||
const x = centerX + Math.cos(angle) * distance
|
||||
const y = centerY + Math.sin(angle) * distance
|
||||
// Hierarchical positioning: levels go top to bottom
|
||||
const yPosition = 100 + (level - 1) * 200 // 200px between levels
|
||||
|
||||
// Get current position for this level
|
||||
let xPosition: number
|
||||
if (level === 1) {
|
||||
// Root nodes: center them horizontally
|
||||
const rootIndex = flowNodes.filter(n => n.data.level === 1).length
|
||||
const rootSpacing = 350
|
||||
const totalRootWidth = (nodes.length - 1) * rootSpacing
|
||||
xPosition = 400 + rootIndex * rootSpacing - totalRootWidth / 2
|
||||
} else {
|
||||
// Child nodes: position relative to parent
|
||||
const currentLevelCount = levelPositions.get(level) || 0
|
||||
levelPositions.set(level, currentLevelCount + 1)
|
||||
|
||||
// Calculate children positions spread around parent
|
||||
const parentNode = flowNodes.find(n => n.id === parentId)
|
||||
if (parentNode) {
|
||||
const siblingCount = node.children?.length || 1
|
||||
const parentChildren = flowNodes.filter(n =>
|
||||
flowEdges.some(e => e.source === parentId && e.target === n.id)
|
||||
).length
|
||||
|
||||
const childSpacing = Math.max(250, 400 / Math.max(siblingCount, 1))
|
||||
const totalWidth = (siblingCount - 1) * childSpacing
|
||||
xPosition = parentX + (parentChildren * childSpacing) - (totalWidth / 2)
|
||||
} else {
|
||||
xPosition = parentX + (currentLevelCount * 300)
|
||||
}
|
||||
}
|
||||
|
||||
flowNodes.push({
|
||||
id: nodeId,
|
||||
type: 'orgNode',
|
||||
position: { x, y },
|
||||
position: { x: xPosition, y: yPosition },
|
||||
data: {
|
||||
node,
|
||||
level
|
||||
}
|
||||
})
|
||||
|
||||
// Add edge from parent
|
||||
// Add edge from parent - center to center diagonal
|
||||
if (parentId) {
|
||||
flowEdges.push({
|
||||
id: `edge-${parentId}-${nodeId}`,
|
||||
source: parentId,
|
||||
target: nodeId,
|
||||
type: 'smoothstep'
|
||||
type: 'straight'
|
||||
})
|
||||
}
|
||||
|
||||
// Process children in a radial pattern around this node
|
||||
const childCount = node.children.length
|
||||
if (childCount > 0) {
|
||||
const angleStep = (2 * Math.PI) / Math.max(childCount, 3)
|
||||
const childDistance = Math.max(150, distance * 0.7)
|
||||
|
||||
// Process children
|
||||
node.children.forEach((child, index) => {
|
||||
const childAngle = angle + (index - (childCount - 1) / 2) * angleStep * 0.8
|
||||
processNode(child, level + 1, nodeId, childAngle, childDistance, x, y)
|
||||
processNode(child, level + 1, nodeId, xPosition, yPosition)
|
||||
})
|
||||
}
|
||||
|
||||
return nodeId
|
||||
}
|
||||
|
||||
// Start with root nodes in a circular pattern
|
||||
const rootCount = nodes.length
|
||||
// Process all root nodes
|
||||
nodes.forEach((node, index) => {
|
||||
const angle = (2 * Math.PI * index) / rootCount
|
||||
const distance = rootCount > 1 ? 200 : 0
|
||||
processNode(node, 1, null, angle, distance)
|
||||
processNode(node, 1, null)
|
||||
})
|
||||
|
||||
return { nodes: flowNodes, edges: flowEdges }
|
||||
|
||||
Reference in New Issue
Block a user