Convert Mouse Events to SVG with Matrix Inversion
Converting client mouse events into local SVG coordinates involves
mapping a point from the browser’s viewport coordinate space into an SVG
element’s internal coordinate system using matrix inversion. Because SVG
elements can be scaled, rotated, translated, and dynamically fitted
using the viewBox attribute, raw screen coordinates
(clientX, clientY) do not match local SVG
units. By taking the element’s Current Transformation Matrix (CTM) and
computing its mathematical inverse, you create an inverted
transformation pipeline that translates raw viewport pixels directly
into the element’s local coordinate space.
The Coordinate Space Mismatch
When a user interacts with a web page, the browser reports pointer
coordinates relative to the visible viewport via properties like
event.clientX and event.clientY. These values
are measured in standard screen pixels starting from the top-left corner
of the browser window.
An SVG graphic, however, exists in its own abstract coordinate space
defined by the viewBox attribute, nested
<g> container transforms, and CSS styling. The
transformation from an SVG’s internal units to screen pixels is
represented as an affine transformation matrix—specifically, the Screen
Current Transformation Matrix (Screen CTM).
The Role of the Current Transformation Matrix (CTM)
The Screen CTM encapsulates every operation applied to the SVG element, including:
- Translation (panning or offset positioning)
- Scaling (resizing or fitting via
preserveAspectRatio) - Rotation and skewing
- Parent container and CSS transformations
Mathematically, the forward transformation maps a local SVG point \((X_{svg}, Y_{svg})\) to a screen coordinate \((X_{screen}, Y_{screen})\):
\[P_{screen} = M \times P_{svg}\]
where \(M\) is the \(3 \times 3\) affine transformation matrix representing the element’s CTM.
Why Inversion is Required
To map a mouse click back into the SVG space, the process must be reversed. You start with the known screen point \(P_{screen}\) and must solve for \(P_{svg}\).
By calculating the inverse of the matrix \(M\) (denoted as \(M^{-1}\)), the equation becomes:
\[P_{svg} = M^{-1} \times P_{screen}\]
Matrix inversion mathematically undoes every transformation in reverse order: - Translations are subtracted rather than added. - Scale factors are divided rather than multiplied. - Rotations are applied in the opposite angular direction.
The Conversion Process in Practice
The browser DOM provides built-in methods to perform this transformation efficiently without requiring manual matrix math.
- Capture Screen Coordinates: When a mouse event
occurs, extract
event.clientXandevent.clientY. - Create an SVG Point: Instantiate a
DOMPoint(orSVGPointin older APIs) using the captured coordinates. - Retrieve the Screen CTM: Call
element.getScreenCTM()on the target SVG element. This returns aDOMMatrixrepresenting the forward transformation from the element’s local space to the viewport. - Invert the Matrix: Call the
.inverse()method on the matrix object to obtain \(M^{-1}\). - Apply the Transformation: Pass the inverted matrix
to
point.matrixTransform(invertedMatrix).
The resulting point object contains the exact \(x\) and \(y\) values corresponding to the target SVG element’s internal coordinate system, regardless of zoom level, viewport resizing, or complex transforms.