Tech NotesApril 20, 2025
Building 2D→3D Floor Plan Sync with Konva.js + Three.js
By Hiramise Team
Hiramise shares a single JSON document between the 2D canvas and the 3D viewer. Moving equipment in 2D instantly reflects in 3D. Here's how we built it.
Coordinate System Design
2D and 3D use different coordinate systems. Konva.js has a top-left origin (Y-down); Three.js has a center origin (Y-up). A shared conversion function bridges them.
- Internal storage unit: mm integers (prevents floating-point error accumulation)
- 2D rendering: mm → pixels (DPR and zoom factor applied)
- 3D rendering: mm → Three.js units (1 unit = 100mm)
- Y-axis flip: floorY = roomHeight_mm − konvaY
Shared JSON Schema
Floor plan data is stored as a single JSON with 3 sections: boundary (walls), equipment (equipment list), and metadata (business type, country).
- boundary: outer + inner wall polylines, mm coordinates
- equipment: id, archetype, x_mm, y_mm, width_mm, depth_mm, rotation_deg
- metadata: country, category, specialty, format
3D Rendering Pipeline
Each equipment entry maps to a GLB model via archetype ID. The model is auto-scaled to match width_mm and depth_mm dimensions.
- Tier 1 (55%): Three.js parametric code — no GLB file needed
- Tier 2–4: GLB uploaded to R2 → loaded via useGLTF
- Scaling: scale.x = targetWidth / modelNativeWidth
- Rotation: rotation.y = −(rotation_deg × π / 180) (Y-axis flip correction)
This architecture means adding a new equipment catalog item only requires one GLB file and one archetype mapping line. No changes to the core renderer.