How to Calculate SVG ViewBox Zoom Center

This article explains the mathematical formulation required to zoom into an arbitrary focal point within an SVG viewBox. Implementing a zoom-to-point interaction requires converting screen coordinates to the SVG coordinate space, calculating the scaled dimensions of the viewBox, and shifting its origin so the target point remains stationary under the cursor.

Understanding the ViewBox Coordinate System

An SVG viewBox is defined by four values:

\[\text{viewBox} = [x_0, y_0, w_0, h_0]\]

When zooming, the goal is to calculate a new viewBox \([x_1, y_1, w_1, h_1]\) based on a zoom scale factor \(s\) (where \(s < 1\) zooms in by decreasing the visible area, and \(s > 1\) zooms out) relative to a focal point \(P(P_x, P_y)\).


Step 1: Convert Screen Coordinates to SVG Coordinates

If the focal point is determined by a user interaction (such as a mouse cursor position \(S(S_x, S_y)\) relative to the rendered SVG container of width \(W_{svg}\) and height \(H_{svg}\)), the screen coordinates must first be mapped into SVG coordinate space:

\[P_x = x_0 + \left( \frac{S_x}{W_{svg}} \right) \cdot w_0\]

\[P_y = y_0 + \left( \frac{S_y}{H_{svg}} \right) \cdot h_0\]


Step 2: Compute the New ViewBox Dimensions

Given a scale multiplier \(s\), the new width \(w_1\) and height \(h_1\) are determined directly by scaling the existing dimensions:

\[w_1 = w_0 \cdot s\]

\[h_1 = h_0 \cdot s\]


Step 3: Compute the New Origin Coordinates

To ensure the point \(P(P_x, P_y)\) remains visually fixed at the same relative position on screen, the normalized ratio of the point within the viewBox must remain invariant before and after the zoom:

\[\frac{P_x - x_0}{w_0} = \frac{P_x - x_1}{w_1}\]

\[\frac{P_y - y_0}{h_0} = \frac{P_y - y_1}{h_1}\]

Rearranging these equations to solve for the new origins \(x_1\) and \(y_1\):

\[x_1 = P_x - \left(\frac{w_1}{w_0}\right) \cdot (P_x - x_0)\]

\[y_1 = P_y - \left(\frac{h_1}{h_0}\right) \cdot (P_y - y_0)\]

Substituting \(s = \frac{w_1}{w_0} = \frac{h_1}{h_0}\) simplifies the formulas to:

\[x_1 = P_x - s \cdot (P_x - x_0)\]

\[y_1 = P_y - s \cdot (P_y - y_0)\]


Summary Formula

To zoom to point \((P_x, P_y)\) by a factor \(s\), update the SVG viewBox with the following parameters: