artistic_qr 1.0.1 copy "artistic_qr: ^1.0.1" to clipboard
artistic_qr: ^1.0.1 copied to clipboard

Customizable artistic QR codes with module shapes, gradients, image halftone, logo blend, 3D effects, animation, and zero dependencies.

example/lib/main.dart

import 'dart:convert';

import 'package:artistic_qr/artistic_qr.dart';
import 'package:flutter/material.dart';

void main() => runApp(const GalleryApp());

const _url = 'https://pub.dev/packages/artistic_qr';

class GalleryApp extends StatelessWidget {
  const GalleryApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'artistic_qr gallery',
      theme: ThemeData(colorSchemeSeed: const Color(0xFF4A148C), useMaterial3: true),
      home: const GalleryPage(),
    );
  }
}

class Demo {
  const Demo(this.title, this.child, {this.subtitle});

  final String title;
  final String? subtitle;
  final Widget child;
}

class GalleryPage extends StatelessWidget {
  const GalleryPage({super.key});

  @override
  Widget build(BuildContext context) {
    final demos = <Demo>[
      const Demo('Classic', ArtisticQrCode(data: _url)),
      Demo(
        'Dots + gradient',
        ArtisticQrCode(
          data: _url,
          style: QrStyle(
            moduleShape: ModuleShape.circle,
            moduleScale: 0.85,
            fill: QrFill.radialGradient(colors: const [Color(0xFF00838F), Color(0xFF1A237E)], radius: 0.9),
            eyeStyle: const QrEyeStyle(
              frame: EyeFrameShape.circle,
              pupil: EyePupilShape.circle,
              frameFill: QrFill.solid(Color(0xFF00838F)),
            ),
          ),
        ),
      ),
      Demo(
        'Fluid + linear gradient',
        ArtisticQrCode(
          data: _url,
          style: QrStyle(
            moduleShape: ModuleShape.fluid,
            fill: QrFill.linearGradient(colors: const [Color(0xFF1565C0), Color(0xFF6A1B9A)]),
            eyeStyle: const QrEyeStyle(frame: EyeFrameShape.rounded(), pupil: EyePupilShape.rounded()),
            // eyeStyleOverrides: {
            //   QrEyePosition.bottomLeft: const QrEyeStyle(
            //     frame: EyeFrameShape.circle,
            //     pupil: EyePupilShape.circle,
            //     frameFill: QrFill.solid(Color(0xFF1565C0)),
            //   ),
            // },
          ),
        ),
      ),
      const Demo(
        'Classy + leaf eyes',
        ArtisticQrCode(
          data: _url,
          style: QrStyle(
            moduleShape: ModuleShape.classy,
            fill: QrFill.solid(Color(0xFF1B5E20)),
            eyeStyle: QrEyeStyle(
              frame: EyeFrameShape.leaf,
              pupil: EyePupilShape.leaf,
              frameFill: QrFill.solid(Color(0xFF2E7D32)),
            ),
          ),
        ),
      ),
      Demo(
        'Sweep gradient + stars',
        ArtisticQrCode(
          data: _url,
          style: QrStyle(
            moduleShape: const ModuleShape.star(),
            moduleScale: 0.95,
            fill: QrFill.sweepGradient(colors: const [Color(0xFFB71C1C), Color(0xFF4A148C), Color(0xFFB71C1C)]),
          ),
        ),
      ),
      const Demo(
        'Per-eye styles',
        ArtisticQrCode(
          data: _url,
          style: QrStyle(
            moduleShape: ModuleShape.circle,
            fill: QrFill.solid(Color(0xFF212121)),
            eyeStyle: QrEyeStyle(
              frame: EyeFrameShape.rounded(),
              pupil: EyePupilShape.circle,
              frameFill: QrFill.solid(Color(0xFFB71C1C)),
              pupilFill: QrFill.solid(Color(0xFFE65100)),
            ),
            eyeStyleOverrides: {
              QrEyePosition.bottomLeft: QrEyeStyle(
                frame: EyeFrameShape.circle,
                pupil: EyePupilShape.circle,
                frameFill: QrFill.solid(Color(0xFF1B5E20)),
                pupilFill: QrFill.solid(Color(0xFF1B5E20)),
              ),
            },
          ),
        ),
      ),
      Demo(
        'Centered logo',
        subtitle: 'QrImageMode.logo — knockout + EC-aware sizing',
        ArtisticQrCode(
          data: _url,
          errorCorrection: QrErrorCorrection.high,
          style: const QrStyle(
            moduleShape: ModuleShape.rounded(),
            eyeStyle: QrEyeStyle(
              frame: EyeFrameShape.rounded(),
              pupil: EyePupilShape.rounded(),
              frameFill: QrFill.solid(Color(0xFF1565C0)),
            ),
          ),
          image: QrImage(source: QrImageSource.asset('assets/logo.png'), mode: const QrImageMode.logo()),
        ),
      ),
      Demo(
        'Color blend',
        subtitle: "QrImageMode.blend — modules take the artwork's colors",
        ArtisticQrCode(
          data: _url,
          errorCorrection: QrErrorCorrection.high,
          style: const QrStyle(
            moduleShape: ModuleShape.circle,
            eyeStyle: QrEyeStyle(
              frame: EyeFrameShape.rounded(),
              pupil: EyePupilShape.circle,
              frameFill: QrFill.solid(Color(0xFF7B1FA2)),
            ),
          ),
          image: QrImage(source: QrImageSource.asset('assets/portrait.png'), mode: const QrImageMode.blend()),
        ),
      ),
      Demo(
        'Halftone photo',
        subtitle: 'QrImageMode.halftone — the "face in the code" effect',
        ArtisticQrCode(
          data: _url,
          errorCorrection: QrErrorCorrection.high,
          image: QrImage(source: QrImageSource.asset('assets/portrait.png'), mode: const QrImageMode.halftone()),
        ),
      ),
      Demo(
        'Colored halftone',
        ArtisticQrCode(
          data: _url,
          errorCorrection: QrErrorCorrection.high,
          image: QrImage(
            source: QrImageSource.asset('assets/portrait.png'),
            mode: const QrImageMode.halftone(colored: true),
          ),
        ),
      ),

      Demo(
        'Colored halftone',
        ArtisticQrCode(
          data: _url,
          errorCorrection: QrErrorCorrection.high,
          style: QrStyle(
            eyeStyle: QrEyeStyle(
              frame: EyeFrameShape.rounded(),
              pupil: EyePupilShape.rounded(),
              frameFill: QrFill.solid(Color(0xFF1565C0)),
              pupilFill: QrFill.solid(Color(0xFF6A1B9A)),
            ),
            eyeStyleOverrides: {
              QrEyePosition.bottomLeft: QrEyeStyle(
                frame: EyeFrameShape.leaf,
                pupil: EyePupilShape.leaf,

                frameFill: QrFill.solid(Color(0xFF1565C0)),
                pupilFill: QrFill.solid(Color(0xFF6A1B9A)),
              ),
            },
          ),
          image: QrImage(
            source: QrImageSource.asset('assets/cr7.png'),
            mode: const QrImageMode.halftone(colored: true),
          ),
        ),
      ),

      Demo(
        'Colored halftone',
        ArtisticQrCode(
          data: _url,

          errorCorrection: QrErrorCorrection.high,
          style: QrStyle(
            eyeStyle: QrEyeStyle(
              frame: EyeFrameShape.rounded(),
              pupil: EyePupilShape.rounded(),
              frameFill: QrFill.solid(Color(0xFF1565C0)),
              pupilFill: QrFill.solid(Color(0xFF6A1B9A)),
            ),
            eyeStyleOverrides: {
              QrEyePosition.bottomLeft: QrEyeStyle(
                frame: EyeFrameShape.leaf,
                pupil: EyePupilShape.leaf,

                frameFill: QrFill.solid(Color(0xFF1565C0)),
                pupilFill: QrFill.solid(Color(0xFF6A1B9A)),
              ),
              QrEyePosition.topRight: QrEyeStyle(
                frame: EyeFrameShape.leaf,
                pupil: EyePupilShape.leaf,

                frameFill: QrFill.solid(Color(0xFF1565C0)),
                pupilFill: QrFill.solid(Color(0xFF6A1B9A)),
              ),
            },
          ),
          image: QrImage(source: QrImageSource.asset('assets/cr7.png'), mode: const QrImageMode.blend()),
        ),
      ),
      Demo(
        'Al-Karamah crest blend',
        subtitle: 'club colors woven into the modules',
        ArtisticQrCode(
          data: _url,
          errorCorrection: QrErrorCorrection.high,
          style: const QrStyle(
            moduleShape: ModuleShape.circle,
            fill: QrFill.solid(Color(0xFF1A237E)),
            eyeStyle: QrEyeStyle(
              frame: EyeFrameShape.rounded(),
              pupil: EyePupilShape.circle,
              frameFill: QrFill.solid(Color(0xFFE65100)),
              pupilFill: QrFill.solid(Color(0xFF1A237E)),
            ),
          ),
          image: QrImage(
            source: QrImageSource.asset('assets/alkarama.png'),
            mode: const QrImageMode.blend(),
          ),
        ),
      ),
      Demo(
        'Al-Karamah center logo',
        ArtisticQrCode(
          data: _url,
          errorCorrection: QrErrorCorrection.high,
          style: const QrStyle(
            moduleShape: ModuleShape.rounded(),
            fill: QrFill.solid(Color(0xFF1A237E)),
            eyeStyle: QrEyeStyle(
              frame: EyeFrameShape.rounded(),
              pupil: EyePupilShape.rounded(),
              frameFill: QrFill.solid(Color(0xFFE65100)),
            ),
          ),
          image: QrImage(
            source: QrImageSource.asset('assets/alkarama.png'),
            mode: const QrImageMode.logo(scale: 0.24),
          ),
        ),
      ),
      Demo(
        'CR7 halftone',
        subtitle: 'the "face in the code" effect',
        ArtisticQrCode(
          data: _url,
          errorCorrection: QrErrorCorrection.high,
          image: QrImage(
            source: QrImageSource.asset('assets/cr7.png'),
            mode: const QrImageMode.halftone(),
          ),
        ),
      ),

      // ---- v0.2 features ----
      Demo(
        'WiFi payload',
        subtitle: 'QrData.wifi — scanning joins the network',
        ArtisticQrCode(
          data: QrData.wifi(ssid: 'CoffeeShop', password: 'espresso42'),
          style: QrStylePresets.ocean,
        ),
      ),
      const Demo(
        '"Scan me" frame',
        subtitle: 'QrFrame — border + label banner',
        ArtisticQrCode(
          data: _url,
          frame: QrFrame(color: Color(0xFF006064)),
          style: QrStyle(
            moduleShape: ModuleShape.fluid,
            fill: QrFill.solid(Color(0xFF006064)),
            eyeStyle: QrEyeStyle(
              frame: EyeFrameShape.rounded(),
              pupil: EyePupilShape.rounded(),
            ),
          ),
        ),
      ),
      Demo(
        '3D blocks',
        subtitle: 'QrEffect.extruded — isometric look',
        ArtisticQrCode(data: _url, style: QrStylePresets.blocks3d),
      ),
      Demo(
        'Floating sticker',
        subtitle: 'QrEffect.shadow',
        ArtisticQrCode(data: _url, style: QrStylePresets.paper),
      ),
      const Demo(
        'Embossed buttons',
        subtitle: 'QrEffect.emboss — raster only',
        ArtisticQrCode(
          data: _url,
          style: QrStyle(
            moduleShape: ModuleShape.rounded(),
            moduleScale: 0.92,
            fill: QrFill.solid(Color(0xFF37474F)),
            effect: QrEffect.emboss(),
            eyeStyle: QrEyeStyle(
              frame: EyeFrameShape.rounded(),
              pupil: EyePupilShape.rounded(),
            ),
          ),
        ),
      ),
      Demo(
        'Preset: sunset',
        subtitle: 'QrStylePresets — 8 ready-made styles',
        ArtisticQrCode(data: _url, style: QrStylePresets.sunset),
      ),
      Demo(
        'Animated gradient sweep',
        subtitle: 'AnimatedArtisticQrCode',
        AnimatedArtisticQrCode(
          data: _url,
          effect: QrAnimationEffect.gradientSweep,
          style: QrStylePresets.candy,
        ),
      ),
      const Demo(
        'Animated reveal',
        AnimatedArtisticQrCode(
          data: _url,
          effect: QrAnimationEffect.reveal,
          duration: Duration(seconds: 2),
          repeat: true,
        ),
      ),
      Demo(
        'Animated pulse',
        AnimatedArtisticQrCode(
          data: _url,
          effect: QrAnimationEffect.pulse,
          style: QrStylePresets.neon,
        ),
      ),
    ];

    return Scaffold(
      appBar: AppBar(
        title: const Text('artistic_qr'),
        actions: [
          IconButton(
            tooltip: 'Export sample PNG + SVG',
            icon: const Icon(Icons.download),
            onPressed: () => _showExports(context),
          ),
        ],
      ),
      body: GridView.builder(
        padding: const EdgeInsets.all(16),
        gridDelegate: const SliverGridDelegateWithMaxCrossAxisExtent(
          maxCrossAxisExtent: 340,
          mainAxisSpacing: 16,
          crossAxisSpacing: 16,
          childAspectRatio: 0.82,
        ),
        itemCount: demos.length,
        itemBuilder: (context, index) {
          final demo = demos[index];
          return Card(
            clipBehavior: Clip.antiAlias,
            child: Padding(
              padding: const EdgeInsets.all(12),
              child: Column(
                children: [
                  Expanded(
                    child: ColoredBox(
                      color: Colors.white,
                      child: Center(child: demo.child),
                    ),
                  ),
                  const SizedBox(height: 8),
                  Text(demo.title, style: Theme.of(context).textTheme.titleSmall),
                  if (demo.subtitle != null)
                    Text(demo.subtitle!, style: Theme.of(context).textTheme.bodySmall, textAlign: TextAlign.center),
                ],
              ),
            ),
          );
        },
      ),
    );
  }

  Future<void> _showExports(BuildContext context) async {
    final qr = await ArtisticQr.create(
      data: _url,
      errorCorrection: QrErrorCorrection.quartile,
      style: QrStyle(
        moduleShape: ModuleShape.fluid,
        fill: QrFill.linearGradient(colors: const [Color(0xFF1565C0), Color(0xFF6A1B9A)]),
        eyeStyle: const QrEyeStyle(frame: EyeFrameShape.rounded(), pupil: EyePupilShape.rounded()),
      ),
    );
    final png = await qr.toPngBytes(pixelSize: 2048);
    final svg = await qr.toSvg(size: 512);
    if (!context.mounted) return;
    showDialog<void>(
      context: context,
      builder: (context) => AlertDialog(
        title: const Text('Headless export'),
        content: SingleChildScrollView(
          child: Text(
            'toPngBytes → ${png.length ~/ 1024} KB PNG at 2048×2048\n'
            'toSvg → ${svg.length ~/ 1024} KB vector SVG\n\n'
            'SVG preview (first 300 chars):\n'
            '${svg.substring(0, 300)}…\n\n'
            'PNG base64 head: ${base64Encode(png).substring(0, 48)}…',
          ),
        ),
        actions: [TextButton(onPressed: () => Navigator.pop(context), child: const Text('Close'))],
      ),
    );
  }
}
15
likes
160
points
164
downloads
screenshot

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

Customizable artistic QR codes with module shapes, gradients, image halftone, logo blend, 3D effects, animation, and zero dependencies.

Repository (GitHub)
View/report issues

Topics

#qr #qr-code #widget #barcode #image

License

MIT (license)

Dependencies

flutter

More

Packages that depend on artistic_qr