Archify viewBox Dimensions Calculation and Overflow Handling

Archify calculates SVG viewBox dimensions through a four-stage pipeline in viewer/viewer-camera.js that computes uniform scaling, derives logical viewport bounds, and applies CSS clip-path to prevent overflow when zooming beyond native resolution.

Archify is an open-source diagram rendering engine that navigates complex SVG structures through sophisticated camera logic. Understanding how Archify handles viewBox dimensions calculation and overflow is essential for developers customizing the viewer or debugging layout issues. The implementation centers on viewer/viewer-camera.js, which transforms logical diagram coordinates into rendered pixels while enforcing strict boundary constraints to keep the visible area within the SVG's declared bounds.

The Four-Stage viewBox Processing Pipeline

The viewer/viewer-camera.js module processes SVG viewBox coordinates through four distinct stages, transforming raw SVG attributes into bounded, user-navigable viewports.

Stage 1: Extracting viewBox Coordinates

At line 19, the camera initializes by extracting the SVGAnimatedRect from the SVG element:

var viewBox = svg.viewBox && svg.viewBox.baseVal;

This retrieval captures the x, y, width, and height attributes that define the logical coordinate system for all subsequent calculations. If the viewBox is invalid (for example, width ≤ 0), the functions return null immediately to prevent division-by-zero errors in scaling calculations.

Stage 2: Computing Content Metrics

The contentMetrics() function (lines 31-40) derives the uniform transformation required to fit the viewBox inside the browser container. It calculates the maximum uniform scale by finding the minimum ratio between container dimensions and viewBox dimensions:

Math.min(width / viewBox.width, height / viewBox.height)

This ensures the diagram maintains its aspect ratio without distortion. The function then computes centering offsets to handle letterboxing:

offsetX = (width - viewBox.width * scale) / 2
offsetY = (height - viewBox.height * scale) / 2

These offsets center the diagram within the container when the aspect ratios differ, providing the foundation for all pan and zoom operations.

Stage 3: Deriving the Logical Viewport

The logicalViewport() function (lines 44-66) maps the current pan and zoom state into viewBox coordinates. On narrow screens (window.innerWidth ≤ 720) displaying wide diagrams, it uses the container's scroll position instead of internal pan state to support horizontal scrolling.

The function enforces hard boundaries by clamping the viewport rectangle:

// Minimum size enforcement and maximum bounds
Math.max(1, Math.min(viewBox.width, width))

// X coordinate clamping to viewBox edges
Math.max(viewBox.x, Math.min(viewBox.x + viewBox.width - width, x))

This logic prevents users from panning into empty space outside the diagram while maintaining a minimum viewport size of 1 logical unit.

Stage 4: Clipping Visual Overflow

When users zoom beyond the natural resolution (scale > 1.001), the clipToViewport() function (lines 101-117) prevents rendering artifacts by applying a CSS clip-path property. This creates an inset() clip that hides any SVG content extending outside the current viewport boundaries.

The clip rectangle recalculates on every animation frame via requestAnimationFrame within the syncViewportClip loop until the camera motion settles (indicated by cameraSettled), ensuring smooth transitions during rapid zoom operations.

Programmatic Viewport Control

Archify exposes the viewBox logic through a public API for building custom navigation controls:

// Retrieve current logical viewport coordinates
const vp = Archify.view.logicalViewport();
console.log(vp);
// → { x: 120, y: 45, width: 800, height: 600, scale: 1.5 }

// Zoom uniformly while respecting viewBox limits
Archify.view.zoom(2.0);
Archify.view.centerAt(400, 300);

// Force clip recalculation after rapid programmatic changes
Archify.view.reveal(['node-123'], { instant: true });

While viewer/viewer-camera.js contains the core transformation logic, several adjacent modules consume these viewBox calculations:

  • viewer/semantic-radar.js: Synchronizes the radar overview minimap using the same viewBox coordinate system
  • viewer/reader-layout.js: Applies viewBox metrics to adjust responsive layouts during window resizing
  • viewer/export.js: Preserves viewBox coordinates when generating exported SVG files

Summary

  • The viewBox pipeline in viewer/viewer-camera.js processes coordinates through four stages: extraction, metric calculation, viewport derivation, and overflow clipping
  • contentMetrics() (lines 31-40) computes uniform scale and centering offsets to fit diagrams without distortion
  • logicalViewport() (lines 44-66) clamps pan coordinates to prevent viewing areas outside the SVG viewBox boundaries
  • CSS clip-path applied by clipToViewport() (lines 101-117) prevents visual overflow when zooming beyond native resolution
  • The viewer supports both responsive scroll-based navigation on mobile and precise programmatic API control

Frequently Asked Questions

How does Archify prevent users from panning outside the diagram boundaries?

Archify enforces boundary constraints in the logicalViewport() function (lines 44-66) by clamping the viewport's x and y coordinates using Math.max() and Math.min() against the viewBox origin and dimensions. This ensures the visible region never exceeds the logical bounds defined by the SVG viewBox, preventing users from dragging empty space into view.

What happens when the SVG lacks a valid viewBox attribute?

If svg.viewBox.baseVal returns null or contains invalid dimensions (where width or height is ≤ 0), the camera functions return null immediately at line 19 of viewer-camera.js. This early exit prevents division-by-zero errors in subsequent scaling calculations and gracefully disables camera controls until a valid viewBox is present.

Why does Archify use CSS clip-path instead of native SVG overflow handling?

Archify applies clip-path through clipToViewport() (lines 101-117) when the zoom scale exceeds 1.001 because it provides hardware-accelerated clipping that updates efficiently during requestAnimationFrame loops. This approach hides overflow content without modifying the SVG DOM structure or triggering expensive layout recalculations that would occur with viewBox attribute manipulation.

How do I programmatically center the view on a specific node while respecting viewBox limits?

Use Archify.view.centerAt(x, y) followed by Archify.view.zoom(level). These methods internally rely on logicalViewport(), which automatically clamps coordinates to valid viewBox ranges before rendering. This ensures the centered point remains visible even when targeting coordinates near the diagram edges.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →