jonacruz/mathcanvas
A lightweight Swift package for rendering math equations natively in SwiftUI using Canvas and CoreGraphics — no WebView, no JavaScript, no dependencies.
Requirements
- iOS 16+ / macOS 13+
- Swift 5.9+
- Xcode 15+
Installation
Add MathCanvas to your project via Swift Package Manager.
In Xcode: File → Add Package Dependencies and enter the repository URL.
In Package.swift:
dependencies: [
.package(url: "https://github.com/jonacruz/MathCanvas", from: "0.1.0")
],
targets: [
.target(
name: "YourTarget",
dependencies: ["MathCanvas"]
)
]Usage
Import the package and use MathCanvas like any SwiftUI view:
import MathCanvas
import SwiftUI
struct ContentView: View {
var body: some View {
VStack(spacing: 24) {
MathCanvas("x^2 + y^2 = 25")
MathCanvas("frac(1,2) + frac(3,4) = frac(5,4)")
.equationFont(size: 32)
MathCanvas("sqrt(x^2 + y^2)")
.equationColor(.blue)
// With a description label below the equation
MathCanvas("frac(3,8)")
.equationDescription("tres octavos")
// Horizontal group of equations
MathCanvasGroup(["frac(2,2)", "frac(3,4)", "frac(7,8)"])
.equationSeparator(",")
MathCanvasGroup(["x^2", "x^3", "x + y", "sin(60)"])
.equationFont(size: 20)
.equationColor(.blue)
}
}
}MathCanvas Modifiers
| Modifier | Description | |---|---| | .equationFont(size:) | Sets the base font size | | .equationColor(:) | Sets the equation color | | .equationDescription(:) | Shows a text label below the equation |
MathCanvasGroup
MathCanvasGroup renders a list of equations in a horizontal scrollable row.
MathCanvasGroup(["frac(1,4)", "frac(2,4)", "frac(3,4)"])
.equationSeparator(",")
.equationFont(size: 28)
.equationColor(.primary)
.equationSpacing(20)| Modifier | Description | |---|---| | .equationFont(size:) | Sets the font size for all equations | | .equationColor(:) | Sets the color for all equations | | .equationSpacing(:) | Sets the spacing between items (default: 16) | | .equationSeparator(_:) | Text rendered between each equation (e.g. ",", "·", "→") |
Syntax
MathCanvas uses its own simple syntax — no LaTeX required.
Numbers and Variables
42 → number
3.14 → decimal
x → variable (rendered in italic)Operators
| Syntax | Result | |---|---| | x + y | Addition | | x - y | Subtraction | | x * y | Multiplication | | x / y | Division | | x ^ 2 | Power / Exponent | | x = y | Equation | | -x | Negation |
Functions
| Syntax | Result | |---|---| | sqrt(x) | Square root with overline | | frac(a, b) | Fraction with horizontal bar | | mfrac(n, a, b) | Mixed fraction: integer part n next to fraction a/b | | sin(x) | Sine | | cos(x) | Cosine | | tan(x) | Tangent | | log(x) | Logarithm |
Examples
x^2 + y^2 = 25
frac(1, 2) + frac(1, 3) = frac(5, 6)
mfrac(1, 1, 2) + mfrac(2, 3, 4)
sqrt(x^2 + y^2)
sin(x)^2 + cos(x)^2 = 1
tan(x) = frac(sin(x), cos(x))
log(x + 1) = y
-b + sqrt(b^2)
frac(sqrt(x), 2)Architecture
MathCanvas processes expressions in three stages:
"x^2 + y^2 = 25"
→ Lexer → [Token]
→ Parser → ASTNode
→ Renderer → MathLayout → CanvasLexer tokenizes the raw string into a flat list of tokens. Parser builds an AST respecting operator precedence and right-associativity for ^. Renderer traverses the AST, computes bounding boxes for each node, and draws using CoreGraphics — giving pixel-perfect layout without any external dependencies.
Roadmap
- [ ] Scaled parentheses that grow with content —
( frac(1,2) ) - [ ] Subscripts —
x_i - [ ] Display vs inline mode
- [ ] Multiplatform SwiftUI preview support
- [ ] Swift 6 concurrency compatibility
License
MIT
Package Metadata
Repository: jonacruz/mathcanvas
Default branch: main
README: README.md