Eigenvalue Finder
A square SVG plane that visualizes the eigen-decomposition of a 2x2 matrix. The unit circle is drawn as a dashed reference; the image of that circle under the matrix is overlaid as an ellipse in accent color. When the eigenvalues are real, each unit eigenvector is rendered as an arrow from the origin scaled by its eigenvalue — geometrically, the directions where the transform aligns (input and output are collinear). When the discriminant is negative, the component falls back to a complex readout and skips the eigenvector arrows.
Installation
npx shadcn@latest add https://craftbits.dev/r/eigenvalue-finder.jsonUsage
import { EigenvalueFinder } from "@craft-bits/core";
<EigenvalueFinder
defaultMatrix={[
[2, 1],
[1, 2],
]}
/>Drive the matrix as a controlled value:
const [matrix, setMatrix] = useState<EigenvalueMatrix2D>([
[2, 1],
[1, 2],
]);
<EigenvalueFinder matrix={matrix} onMatrixChange={setMatrix} />A rotation matrix — complex conjugate eigenvalues, no real eigenvectors:
<EigenvalueFinder
matrix={[
[Math.cos(Math.PI / 4), -Math.sin(Math.PI / 4)],
[Math.sin(Math.PI / 4), Math.cos(Math.PI / 4)],
]}
/>Hide the unit circle to focus on the ellipse:
<EigenvalueFinder
matrix={[[3, 0], [0, 0.5]]}
showUnitCircle={false}
/>Understanding the component
- Closed-form 2x2 eigen-decomposition. Eigenvalues are the roots of the characteristic polynomial
lambda squared minus trace times lambda plus det = 0. The discriminanttrace squared minus 4 detdecides the branch — non-negative gives two real eigenvalues, negative gives a conjugate pair. - Unit eigenvectors from the null space. For each real eigenvalue, the eigenvector is solved from
A minus lambda I times v equals 0and normalized. A numerically safe branch picks whichever row ofA minus lambda Ihas larger magnitude — that avoids dividing by a near-zero pivot at scalar multiples of the identity. - Unit circle as the input space. Every point on the dashed circle is a unit input vector. The image of the circle under the matrix is an ellipse drawn alongside the eigenvector arrows.
- Eigenvectors as fixed directions. Each unit eigenvector is drawn as a dashed faint segment of length one; the same direction scaled by lambda is drawn as a solid arrow. When the matrix acts on an eigenvector the result lies on the same line — the dashed input and solid output share a direction.
- Two tones for two eigenvectors.
lambda 1(sorted as the larger) draws invar(--cb-accent);lambda 2draws invar(--cb-warning). Color matches the readout chip below. - Auto-fit viewport. The viewport is sized so the largest of the eigenvalue magnitudes and the matrix's row norms comfortably fits, with a 30 percent margin.
- Complex case fallback. When the discriminant is negative the component skips the eigenvector arrows (no real direction exists) and surfaces a complex readout under the plot. The ellipse still renders, so rotations still make visual sense.
- Spring transitions. The ellipse polyline and the eigenvector arrows animate with
SPRINGS.smoothbetween matrix changes.prefers-reduced-motion: reducecollapses every spring toduration: 0.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
matrix | EigenvalueMatrix2D | — | Controlled 2x2 matrix. Pair with onMatrixChange. |
defaultMatrix | EigenvalueMatrix2D | identity | Uncontrolled initial matrix. |
onMatrixChange | (next: EigenvalueMatrix2D) => void | — | Fires when the matrix changes. |
showUnitCircle | boolean | true | Render the dashed input unit circle. |
showTransformedEllipse | boolean | true | Render the image of the unit circle (ellipse). |
showEigenvectors | boolean | true | Render eigenvector arrows when real. |
range | readonly [number, number] | auto | Visible math-space domain on both axes. |
size | number | 320 | SVG side length in pixels (the plane is square). |
transition | Transition | SPRINGS.smooth | Spring for ellipse / eigenvector transitions. |
className | string | — | Merged onto the root <div> via cn(). |
The EigenvalueMatrix2D shape is a row-major tuple — [[a, b], [c, d]] represents
| a b |
| c d |
Accessibility
- The SVG is
role="img"with anaria-labelledbyheading also rendered as a visually hiddenaria-live="polite"summary — assistive tech announces the eigenvalues and eigenvectors as the matrix changes. - The visualization is read-only; there are no interactive handles inside the plot, so no keyboard or pointer behaviour to enumerate.
- The eigenvalue readout uses tabular numerals so the columns stay aligned as values change.
- Animation respects
prefers-reduced-motion: reduce— every spring collapses to an instant swap.
Credits
- Extracted from:
craftingattention(app/src/lessons/primitives/math/EigenvalueFinder.tsx). The source paired a polynomial-plot dragger with a column-vector parallelism check and a snap-to-root narration state machine. The library extract is the pure visualization primitive — the unit circle, its image ellipse, the eigenvectors as arrows, and the eigenvalue readout.