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]\]
- \(x_0, y_0\): The top-left origin coordinates of the current viewport.
- \(w_0, h_0\): The current width and height of the viewport.
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:
- \(\text{min-x} = P_x - s \cdot (P_x - x_0)\)
- \(\text{min-y} = P_y - s \cdot (P_y - y_0)\)
- \(\text{width} = w_0 \cdot s\)
- \(\text{height} = h_0 \cdot s\)