A Reusable 3D Pipeline Dashboard: Map, Topology, and Spatial Flow in Three.js
Dashboard projects often collapse under their own complexity when transparency sorting, camera controls, and multi-module animation states collide. This demo packages five concrete, battle-tested patterns—the net-zero camera sway, global-direction pipe offset, three-stage render order, combinatorial preset switching, and the orchestrator module split—that can be lifted individually into any Three.js visualization without adopting the whole framework.
Built on real Handan city GeoJSON and 136 pipeline segments, this Three.js and ECharts demo layers a glowing topology network onto a geographic base map. Supply and return pipes run as parallel Catmull-Rom curves, offset by a global direction vector to avoid self-intersection at bends, while particles stream in opposite directions along each path. A three-layer pipe construction—solid inner, semi-transparent outer glow, and flowing particles—uses explicit renderOrder and depthWrite:false to fix transparency sorting across the scene.
A camera micro-sway system coexists with OrbitControls by undoing the previous frame's offset before the controls update, then reapplying a new sway, creating a net-zero loop that never corrupts user drag state. The high-altitude compute engine switches between four visual presets by destroying and rebuilding its entire group, with one preset cycling through polyhedral morphs on each scan pulse.
The architecture follows a strict orchestrator pattern: SceneManager owns the stage and dispatches per-frame updates to self-contained modules like NetworkBuilder, MapBuilder, and ComputeEngine, each holding references to scene, camera, and controls but managing its own meshes and animations independently.
The global-direction offset for parallel pipes is a deliberate trade-off: it sacrifices physical accuracy at sharp bends for guaranteed visual stability, which is the right call for a dashboard where no one measures pipe spacing.
Undoing camera sway before the controls update, rather than trying to integrate sway into the controls themselves, is a cleaner separation of concerns—OrbitControls never knows sway exists, so its damping and state machine remain untouched.
The three-stage render order with universal depthWrite:false is effectively a manual painter's algorithm for a scene where WebGL's default transparency sorting would fail; it works because the scene's depth complexity is known and fixed.
Disposing and rebuilding the entire engine group on preset switch is brute-force but eliminates an entire class of bugs where lingering meshes, particles, or labels from the old preset contaminate the new one.