custom-canvas-and-gestures

Enforces CustomPainter discipline for Flutter canvas rendering, hit-testing, gestures, and semantics.

Updated Aug 22, 2026
One-click install
npx skills add https://github.com/zakariaf/NearlyStop --skill custom-canvas-and-gestures-zakariaf
Or copy as Structured Prompt for Agent
Please help me install this Agent Skill.
Skill: custom-canvas-and-gestures
Source: https://github.com/zakariaf/NearlyStop/tree/main/.claude/skills/custom-canvas-and-gestures
Command: npx skills add https://github.com/zakariaf/NearlyStop --skill custom-canvas-and-gestures-zakariaf

SYSTEM DOCUMENTATION & REQUIREMENTS

💡 This Skill includes scripts (resource) and references (resource) components.

What problem does it solve? Hand-painted Flutter surfaces built with CustomPainter and Canvas often suffer from silent defects: painters that repaint every frame, hit-testers that disagree with the painter by a few pixels, allocations inside paint() causing jank, and canvases that are completely opaque to screen readers. This Skill provides a strict architectural contract so custom-drawn surfaces stay performant, testable, and accessible. ## Core Features & Use Cases - View/Painter/Scene architecture: Splits every canvas surface into a View, a dumb CustomPainter, and an immutable Scene value type so shouldRepaint becomes a single cheap value compare. - Shared transform and O(1) hit-testing: One affine transform read by both painter and hit-tester, with integer lattice math or a rasterized region-ID buffer instead of Path.contains in the touch path. - Gesture and semantics discipline: Gesture handlers act as pure translators emitting typed commands to a Riverpod Notifier, while ExcludeSemantics plus sibling Semantics nodes make the canvas speak display values to screen readers. - Use Case: When building a custom chart, grid, or interactive canvas in Flutter, apply this Skill to structure the painter, wire tap/drag hit-testing through a shared transform, drive animation via an AnimationController as the repaint Listenable, and pass the included hygiene scripts before a PR. ## Quick Start Review my CustomPainter implementation and fix any violations of the View/Painter/Scene split, shared transform, and zero-allocation paint rules.

Frequently Asked Questions about custom-canvas-and-gestures

High-intent search queries and answers about installing and using this skill.

FAQPage Schema
How do I structure a Flutter CustomPainter for testability?

Split the surface into three collaborators: a View that watches the ViewModel, a dumb CustomPainter that only draws, and an immutable Scene value type holding everything the painter needs. The painter holds no Notifier, BuildContext, or domain rules, making it a pure function of the Scene that you can golden-test directly.

How do I hit-test taps on a custom canvas in Flutter?

Map TapDownDetails.localPosition through the shared transform's toLogical method, then use geometry-class hit-testing: integer floor division for regular grids, or a Uint32List region-ID buffer rasterized once at load for irregular shapes. Never call Path.contains in the touch path or re-derive scale from size.

Why does my CustomPainter repaint every frame?

A shouldRepaint that returns true repaints on every frame even when idle. Because the Scene is a value type with equality, shouldRepaint should be a single compare: old.scene != scene. Per-frame animation should flow through an AnimationController passed as the repaint Listenable, not through shouldRepaint.

How do I make a custom-painted widget accessible to screen readers?

Wrap the CustomPaint in ExcludeSemantics and add a sibling Semantics node that speaks the display value, such as the trend or total, rather than describing the shape. For per-element nodes, return CustomPainterSemantics from semanticsBuilder and ensure the accessibility action commits the same command as the gesture.

What causes jank inside a CustomPainter paint method?

Allocating Paint, Path, or Gradient objects inside paint() churns the garbage collector on the raster thread. Hoist every Paint and geometry-stable Path to painter fields, mutate .color per element instead of constructing, and reserve saveLayer for genuine group opacity or blends.

Should I use figma_squircle or smooth_corner for squircle shapes in Flutter?

No. Flutter now provides first-party RoundedSuperellipseBorder, ClipRSuperellipse, and Canvas.drawRSuperellipse with an Impeller GPU fast path. ContinuousRectangleBorder is not an iOS-grade squircle, and third-party squircle packages are unnecessary dead weight.