Introduction
Capturing a user signature on mobile is a common requirement in flutter mobile development. A robust signature widget should feel natural to draw, store the vector form (not just a bitmap), and export to standards like SVG or PDF for printing and archival. This tutorial walks through designing a lightweight signature capture widget that records strokes as vector paths, renders them smoothly, and exports them as an SVG path string (and describes how to include that in PDF exports).
Designing The Signature Widget
Start by separating concerns: input capture, path model, rendering, and export. The model stores strokes: each stroke is a list of sampled points with pressure/tilt optional metadata. The renderer turns strokes into a Path and paints with stroke attributes. The widget itself uses GestureDetector (or Listener) to sample pointer events and append points to the active stroke.
Keep the public API minimal: clear(), undo(), exportSvg(), exportPdf(), and an optional onChange callback. This makes the widget composable in forms and easy to test.
Capturing And Rendering Paths
Sampling: use PointerMove events and sample at device pixel coordinates; throttle if extremely frequent. Store points with timestamps to allow velocity-based smoothing if desired. For smoothness, convert point lists to quadratic Bezier segments using a moving-average or midpoint algorithm. You can keep a simple algorithm that produces visually pleasing strokes without heavy math.
Rendering: implement a CustomPainter that iterates strokes, constructs a Path with moveTo + quadraticBezierTo, and paints with strokeCap round and strokeJoin round. If you want variable width (pressure), create a mesh or stroke polygon; for many applications a fixed strokeWidth is sufficient and simpler to export as vector.
Basic capture + paint snippet (stateful widget with sampling and painter):
class _SignatureState extends State<Signature> {
List<List<Offset>> strokes = [];
List<Offset> current = [];
void _start(Offset p) => current = [p];
void _update(Offset p) { current.add(p); setState((){}); }
void _end() { strokes.add(current); current = []; setState((){}); }
}
This snippet is intentionally compact; production code should handle pointers with IDs for multi-touch safety and integrate onPanCancel.
Exporting As SVG And PDF
SVG is straightforward when you have vector point data. Build an SVG path data string (the "d" attribute) by iterating stroke points and using 'M' for the first point then 'Q' segments for smoothed points. Preserve strokeWidth, stroke color, and linecap/linejoin attributes in the resulting elements. Embedding multiple strokes as separate elements keeps editing possibilities.
Simple conversion to SVG path data (quadratic smoothing):
String pointsToSvgPath(List<Offset> pts) {
if (pts.isEmpty) return '';
final b = StringBuffer()..write('M ${pts[0].dx} ${pts[0].dy}');
for (int i = 1; i < pts.length - 1; i++) {
final c = pts[i]; final n = pts[i+1];
b.write(' Q ${c.dx} ${c.dy} ${ (c.dx+n.dx)/2 } ${ (c.dy+n.dy)/2 }');
}
b.write(' L ${pts.last.dx} ${pts.last.dy}');
return b.toString();
}For PDF export, convert the same path data into the PDF drawing commands or render the SVG onto a PDF canvas using a library like pdf (dart_pdf) which accepts Path operations. When exporting to PDF, ensure you apply the same coordinate transforms (page margins, scale) so the signature appears at the correct size.
Optimization And Best Practices
Sampling Rate: Limit sample frequency to a reasonable rate (e.g., 60–120Hz) and interpolate between samples to reduce data volume.
Memory: Store minimal per-point data (x,y,t) and defer heavy operations (like building Path objects) to the painter to avoid duplicating memory.
Smoothing: Use lightweight smoothing (midpoint/Beziers) rather than full spline algorithms unless you need extreme fidelity.
Scaling: Always record coordinates in a widget-local coordinate system. For exports, apply transforms to map to target DPI/units so signatures scale predictably across screens and printed pages.
Accessibility: Provide a text alternative when signatures are optional and confirm with users before saving biometric-like data.
Vibe Studio

Vibe Studio, powered by Steve’s advanced AI agents, is a revolutionary no-code, conversational platform that empowers users to quickly and efficiently create full-stack Flutter applications integrated seamlessly with Firebase backend services. Ideal for solo founders, startups, and agile engineering teams, Vibe Studio allows users to visually manage and deploy Flutter apps, greatly accelerating the development process. The intuitive conversational interface simplifies complex development tasks, making app creation accessible even for non-coders.
Conclusion
A production-ready signature widget in flutter mobile development is achievable with a small, well-separated architecture: capture strokes, smooth and render with CustomPainter, and export vector data as SVG (and to PDF via conversion). Vector export preserves fidelity, scales cleanly for printing, and keeps files compact. Start with simple fixed-width strokes and add pressure/tilt or variable-width rendering only if your app requires higher fidelity.