Skip to main content

infinite_math_plot 0.1.1 copy "infinite_math_plot: ^0.1.1" to clipboard
infinite_math_plot: ^0.1.1 copied to clipboard

A Flutter package that renders interactive mathematical graphs on a simulated infinite coordinate plane.

InfiniteMathPlot #

A Flutter package for plotting interactive mathematical graphs. You give it an equation string, it draws the curve. Zoom in, zoom out, pan around — it just works.

I built this because every graphing widget I found either required you to pre-compute points yourself, didn't handle discontinuities properly, or fell apart when you zoomed in too far. This one handles all of that internally.


What it can do #

  • Plot Cartesian, implicit, parametric, and polar equations from a plain string
  • Handle discontinuities automatically — tan(x), 1/x, sqrt(x) all render correctly without any extra configuration
  • Zoom and pan with pinch gestures, scroll wheel, or drag
  • Plot multiple curves on the same graph, each with its own color
  • Draw a grid and labeled axes that scale with the viewport
  • Adapt to any screen size — works on mobile, tablet, desktop, and web

Installation #

Add this to your pubspec.yaml:

dependencies:
  infinite_math_plot: ^0.1.1

Run flutter pub get, then import it:

import 'package:infinite_math_plot/infinite_math_plot.dart';

Getting started #

The simplest usage is just dropping the widget somewhere and giving it an equation:

InfiniteMathPlot(
  equation: 'y = sin(x)',
)

That gives you a full-screen interactive graph with a grid, axes, and a blue sine curve. You can already zoom and pan at this point.

If you want to control the initial view:

InfiniteMathPlot(
  equation: 'y = x^2',
  xMin: -5,
  xMax: 5,
  yMin: -1,
  yMax: 10,
)

Equation types #

Cartesian #

The standard y = f(x) form. Just write the right-hand side:

InfiniteMathPlot(equation: 'y = sin(x)')
InfiniteMathPlot(equation: 'y = x^3 - 2*x + 1')
InfiniteMathPlot(equation: 'y = 1/x')       // asymptote at x=0, handled automatically
InfiniteMathPlot(equation: 'y = sqrt(x)')   // undefined for x < 0, handled automatically
InfiniteMathPlot(equation: 'y = abs(x - 2)')

Implicit #

Equations with both x and y. The package finds the zero-level set using marching squares:

InfiniteMathPlot(equation: 'x^2 + y^2 = 25')    // circle
InfiniteMathPlot(equation: 'x^2/9 + y^2/4 = 1') // ellipse
InfiniteMathPlot(equation: 'y^2 = x^3 - x')     // elliptic curve

Parametric #

Both x and y as functions of t, separated by a comma. t runs from 0 to 2π:

InfiniteMathPlot(equation: 'x = cos(t), y = sin(t)')       // circle
InfiniteMathPlot(equation: 'x = sin(3*t), y = sin(2*t)')   // Lissajous figure
InfiniteMathPlot(equation: 'x = t*cos(t), y = t*sin(t)')   // spiral

Polar #

r as a function of the angle. Use theta or θ:

InfiniteMathPlot(equation: 'r = cos(3*theta)')    // 3-petal rose
InfiniteMathPlot(equation: 'r = 1 + cos(theta)')  // cardioid
InfiniteMathPlot(equation: 'r = theta')           // Archimedean spiral

Plotting multiple curves #

Use equations instead of equation and pass a list of EquationConfig objects:

InfiniteMathPlot(
  equations: [
    EquationConfig(equation: 'y = sin(x)', color: Colors.blue),
    EquationConfig(equation: 'y = cos(x)', color: Colors.orange),
    EquationConfig(equation: 'y = sin(x) * cos(x)', color: Colors.green, strokeWidth: 1.5),
  ],
)

You can't use both equation and equations at the same time — the widget will throw an assertion error if you try.


Customization #

Turning off grid or axes #

InfiniteMathPlot(
  equation: 'y = x^2',
  showGrid: false,   // no grid lines
  showAxes: false,   // no axes or tick labels
)

Disabling gestures #

// Static graph, no interaction
InfiniteMathPlot(
  equation: 'y = sin(x)',
  enableZoom: false,
  enablePan: false,
)

Changing the curve style #

InfiniteMathPlot(
  equation: 'y = sin(x)',
  graphColor: Colors.deepPurple,
  strokeWidth: 3.0,
)

Sampling precision #

The default is 2 sample points per logical pixel, which looks good for most equations. If you're plotting something with rapid oscillations (like y = sin(50*x)), bump it up:

InfiniteMathPlot(
  equation: 'y = sin(50*x)',
  samplingPrecision: 4.0,
)

For simple equations where performance matters more than smoothness, you can lower it:

InfiniteMathPlot(
  equation: 'y = x',
  samplingPrecision: 1.0,
)

All parameters #

InfiniteMathPlot #

Parameter Type Default What it does
equation String? — Single equation. Use this or equations, not both.
equations List<EquationConfig>? — Multiple equations. Use this or equation, not both.
xMin double -10 Left edge of the initial viewport.
xMax double 10 Right edge of the initial viewport.
yMin double -10 Bottom edge of the initial viewport.
yMax double 10 Top edge of the initial viewport.
showGrid bool true Whether to draw grid lines.
showAxes bool true Whether to draw axes and tick labels.
enableZoom bool true Whether pinch and scroll-wheel zoom is active.
enablePan bool true Whether drag-to-pan is active.
graphColor Color Colors.blue Curve color (single-equation mode only).
strokeWidth double 2.0 Curve thickness in logical pixels (single-equation mode only).
samplingPrecision double 2.0 Sample points per logical pixel. Higher = smoother.

EquationConfig #

Field Type Default What it does
equation String required The equation string.
color Color required Curve color.
strokeWidth double 2.0 Curve thickness in logical pixels.

Supported math #

Functions #

sin, cos, tan, asin, acos, atan, sqrt, abs, exp, log, pow

'y = sin(x)'
'y = pow(x, 3)'    // same as x^3
'y = exp(x)'       // same as e^x
'y = log(x)'       // natural log

Constants #

pi, π, e

'y = sin(pi * x)'
'y = e^x'

Operators #

+, -, *, /, ^ (exponentiation)

A few things to watch out for:

  • Use ^ for powers, not **
  • Always write * explicitly — 2x won't parse, 2*x will
  • For polar equations, use theta or θ as the angle variable

A note on discontinuities #

The package distinguishes between two situations that look similar but are actually different:

True asymptotes — like 1/x near x=0 or tan(x) near π/2. The function jumps from a large positive value to a large negative value (or vice versa) as it crosses through the viewport. The package detects this and breaks the path there, so you don't get a spurious vertical line connecting the two branches.

Steep but continuous functions — like y = x³ when you're zoomed out. The y-values can be enormous (x=10 gives y=1000), but the function is perfectly continuous. The package does not break the path here, even though the jump between consecutive samples is large. It correctly identifies that both values are on the same side of the viewport and keeps the curve connected.

This distinction matters because a naive "break the path if the jump is too large" approach would shred x³ into fragments when zoomed out. The package avoids that by requiring that a suspected asymptote has values straddling the viewport — one above yMax and one below yMin — before breaking the path.


Running the example app #

There's a demo app in the example/ folder:

cd example
flutter run

It has 8 preset equations you can switch between, a text field where you can type any equation and plot it live, and toggles for grid, axes, zoom, and pan. Good for quickly testing what the package can do.


Running the tests #

flutter test

There are 241 tests covering the parser, coordinate transformer, discontinuity detector, sample generator, painter, gesture handler, and the top-level widget. The test suite includes property-based round-trip tests (parse → serialize → parse, screen → math → screen) in addition to regular unit and widget tests.


Common issues #

Gaps in the curve where there shouldn't be any

This usually means the equation has a domain restriction the package is respecting. sqrt(x) is undefined for negative x, so the left half of the graph will be empty. log(x) is undefined for x ≤ 0. This is correct behavior, not a bug.

If you're seeing gaps in a function that should be continuous everywhere, check whether samplingPrecision is high enough. Very rapidly oscillating functions need more samples to render correctly.

Parse error on a valid-looking equation

A few syntax rules to check:

  • Multiplication must be explicit: write 2*x, not 2x
  • Use ^ for exponentiation: x^2, not x**2
  • Parametric equations need a comma between the two parts: x = cos(t), y = sin(t)
  • For polar, the angle variable is theta or θ, not t

Hot reload fails with "Const class cannot become non-const"

This is a Flutter hot reload limitation. The GestureHandler class holds mutable zoom state (_lastScale) so it can't be const. Just do a hot restart (R in the terminal, or the restart button in your IDE) instead of hot reload. Hot restart picks up all changes cleanly.


License #

MIT

1
likes
130
points
12
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

A Flutter package that renders interactive mathematical graphs on a simulated infinite coordinate plane.

Repository (GitHub)
View/report issues

License

MIT (license)

Dependencies

flutter, math_expressions

More

Packages that depend on infinite_math_plot