如何实现Tweakpane与3d-force-graph的集成,点击节点时展示属性并保留现有缩放功能
Solution: Display Node Properties in Tweakpane on Node Click for 3D-Force-Graph
Let's integrate the node property display with your existing onNodeClick zoom functionality, using Tweakpane to create a clean, passive info panel that shows all node attributes plus adjacent connections. Here's a step-by-step implementation:
1. Initialize Tweakpane with Dynamic Folders
First, set up your Tweakpane instance with dedicated folders for node details and adjacent connections. We'll use a dynamic object to hold the selected node's data, which we'll update on each click:
// Initialize Tweakpane const pane = new Pane(); // Create folders for organized display const nodeDetailsFolder = pane.addFolder({ title: 'Selected Node Details', expanded: true }); const adjacentFolder = pane.addFolder({ title: 'Adjacent Nodes & Links', expanded: false }); // Dynamic object to store current node's properties (updated on click) let currentNodeParams = {};
2. Create a Helper Function to Update the Panel
This function will clear old content, populate the panel with the selected node's properties, and fetch adjacent connections:
function updateNodeDetails(node) { // Clear existing controls to avoid duplication nodeDetailsFolder.clear(); // Map basic node properties to our dynamic object currentNodeParams = { Label: node.label, ID: node.id, Description: node.description, Type: node.type, Size: node.size, Color: node.color, Position: { x: node.x.toFixed(2), y: node.y.toFixed(2), z: node.z.toFixed(2) } }; // Add basic properties to the panel (set to read-only) nodeDetailsFolder.addBinding(currentNodeParams, 'Label').disabled(true); nodeDetailsFolder.addBinding(currentNodeParams, 'ID').disabled(true); nodeDetailsFolder.addBinding(currentNodeParams, 'Description').disabled(true); nodeDetailsFolder.addBinding(currentNodeParams, 'Type').disabled(true); nodeDetailsFolder.addBinding(currentNodeParams, 'Size', { disabled: true }); nodeDetailsFolder.addBinding(currentNodeParams, 'Color', { disabled: true }); nodeDetailsFolder.addBinding(currentNodeParams, 'Position', { disabled: true }); // Add nested graph metrics from the `attributes` object const metricsFolder = nodeDetailsFolder.addFolder({ title: 'Graph Metrics', expanded: false }); Object.entries(node.attributes).forEach(([key, value]) => { currentNodeParams[key] = value; metricsFolder.addBinding(currentNodeParams, key).disabled(true); }); // Update adjacent connections section updateAdjacentNodesAndLinks(node); } function updateAdjacentNodesAndLinks(node) { adjacentFolder.clear(); const graph = yourForceGraphInstance.graphData(); // Replace with your graph instance variable // Fetch connected nodes and links using 3d-force-graph's built-in methods const connectedNodes = graph.getConnectedNodes(node.id); const connectedLinks = graph.getNodeLinks(node.id); // Display adjacent nodes as a read-only text area const nodeLabels = connectedNodes.map(n => n.label).join('\n'); adjacentFolder.addInput( { 'Adjacent Nodes': nodeLabels }, 'Adjacent Nodes', { readonly: true, rows: Math.min(connectedNodes.length, 5) } ); // Display adjacent links (source → target pairs) const linkPairs = connectedLinks.map(link => `${link.source.label} → ${link.target.label}`).join('\n'); adjacentFolder.addInput( { 'Adjacent Links': linkPairs }, 'Adjacent Links', { readonly: true, rows: Math.min(connectedLinks.length, 5) } ); }
3. Integrate with Your Existing onNodeClick Logic
Modify your existing click handler to run the zoom logic and update the Tweakpane panel:
yourForceGraphInstance .onNodeClick(node => { // Existing zoom-to-node logic const distance = 40; const distRatio = 1 + distance/Math.hypot(node.x, node.y, node.z); const newPos = node.x || node.y || node.z ? { x: node.x * distRatio, y: node.y * distRatio, z: node.z * distRatio } : { x: 0, y: 0, z: distance }; // Handle (0,0,0) node case // Move camera to focus on the node (adjust duration as needed) yourForceGraphInstance.cameraPosition(newPos, node, 300); // Update Tweakpane with node details updateNodeDetails(node); });
Key Notes
- Read-only Controls: All panel elements are set to
disabledorreadonlyto maintain passive display, as requested. - Dynamic Updates: The
clear()method ensures old node data is removed before adding new content, preventing cluttered panels. - Adjacent Connections: Uses 3d-force-graph's built-in
getConnectedNodesandgetNodeLinksmethods to fetch related data efficiently. - Formatting: Position values are rounded to 2 decimal places for readability, but you can adjust this as needed.
内容的提问来源于stack exchange,提问作者greg.gan
相关产品推荐
相关产品推荐

