scratch_3d_card
A Flutter widget that renders an animated 3D scratch gift card. Scratch the overlay to reveal a reward, tap the header to flip the card, and watch the whole thing tilt in real-time based on gyroscope input.
Preview
Scratching

Win

Card

Features
- Scratch to reveal — draw over the overlay with a finger or mouse; scratched areas disappear cleanly using
BlendMode.clear - Particle chips — small debris rectangles fly off the scratch brush while scratching
- 3D gyroscope tilt — the card tilts in perspective as you physically tilt your device
- Card flip — when a header is shown (
logoorlogoText), tap it to flip the entire card front ↔ back with a smooth 3D animation - Customizable back face — solid color + text, a full-bleed image, or any widget
- Outer shell — style the surrounding container (color, padding, corners, shadow); it participates fully in the flip
- Completion callback — get notified when the user has scratched past a configurable threshold
Getting started
Add to your pubspec.yaml:
dependencies:
scratch_3d_card: ^0.1.0
Gyroscope permissions
The 3D tilt feature uses sensors_plus. No extra permissions are needed on iOS or Android for the gyroscope, but if you target Android 12+ you may want to confirm HIGH_SAMPLING_RATE_SENSORS is not required for your use case (it is not needed at the default game interval).
To disable tilt entirely, pass enable3DTilt: false.
Usage
import 'package:scratch_3d_card/scratch_3d_card.dart';
Scratch3DCard(
// Outer shell — this entire container flips
containerColor: Colors.white,
containerPadding: const EdgeInsets.all(20),
containerBorderRadius: BorderRadius.circular(22),
containerShadow: [
BoxShadow(color: Colors.black12, blurRadius: 20, offset: Offset(0, 4)),
],
// Header — tap to flip
logo: Icon(Icons.apple, size: 22),
logoText: ' giftcard',
// Scratch overlay
cardColor: Color(0xFF2C2C2E),
scratchChipColor: Colors.white70,
scratchToRevealText: 'Scratch to reveal',
brushSize: 50,
width: 320,
height: 200,
// Completion
completionThreshold: 0.65,
onComplete: () => print('Revealed!'),
// Back face (shown when flipped)
backCardColor: Color(0xFF1C1C1E),
backText: 'Gift Card',
// Revealed content underneath the overlay
child: Container(
color: Colors.white,
alignment: Alignment.center,
child: Text('You won \$24', style: TextStyle(fontSize: 26, fontWeight: FontWeight.bold)),
),
)
Parameters
Front face
| Parameter | Type | Default | Description |
|---|---|---|---|
child |
Widget |
required | Content revealed after scratching |
cardColor |
Color |
#2C2C2E |
Scratch overlay background color |
scratchChipColor |
Color |
Colors.white |
Color of particle chips during scratch |
scratchToRevealText |
String |
'Scratch to reveal' |
Hint text on the overlay |
brushSize |
double |
45.0 |
Scratch brush radius in logical pixels |
completionThreshold |
double |
0.65 |
Fraction scratched (0–1) to trigger reveal |
onComplete |
VoidCallback? |
null |
Called once when threshold is reached |
logo |
Widget? |
null |
Widget shown in the header row |
logoText |
String? |
null |
Text shown beside the logo |
logoTextStyle |
TextStyle? |
null |
Style for logo text |
borderRadius |
BorderRadius |
circular(18) |
Corner radius of the scratch area |
width |
double |
320 |
Scratch area width |
height |
double |
200 |
Scratch area height |
Outer shell
| Parameter | Type | Default | Description |
|---|---|---|---|
containerColor |
Color |
Colors.white |
Background of the outer card shell |
containerPadding |
EdgeInsets |
all(20) |
Padding inside the shell |
containerBorderRadius |
BorderRadius |
circular(22) |
Outer shell corner radius |
containerShadow |
List<BoxShadow> |
soft shadow | Shadows on the shell |
Back face
| Parameter | Type | Default | Description |
|---|---|---|---|
showBackInitially |
bool |
false |
Start with back face visible |
backCardColor |
Color |
#1C1C1E |
Back face background color |
backText |
String? |
null |
Centered text on the back |
backTextStyle |
TextStyle? |
null |
Style for back text |
backImage |
ImageProvider? |
null |
Full-bleed image for the back |
backChild |
Widget? |
null |
Fully custom back widget (overrides text/image) |
3D tilt
| Parameter | Type | Default | Description |
|---|---|---|---|
enable3DTilt |
bool |
true |
Enable gyroscope-driven tilt |