import 'package:flutter/material.dart'; import 'dart:math'; /// Widget untuk efek kertas struk tersobek di bagian atas class ReceiptTearTop extends StatelessWidget { const ReceiptTearTop({super.key}); @override Widget build(BuildContext context) { return Container( width: 360.0, // Lebar tetap sesuai dengan kontainer struk color: Colors.grey[300], // Warna latar belakang sesuai dengan latar belakang layar child: CustomPaint( size: const Size(360.0, 20), // Lebar tetap, tinggi 20 painter: _TearPainter(isTop: true), ), ); } } /// Widget untuk efek kertas struk tersobek di bagian bawah class ReceiptTearBottom extends StatelessWidget { const ReceiptTearBottom({super.key}); @override Widget build(BuildContext context) { return Container( width: 360.0, // Lebar tetap sesuai dengan kontainer struk color: Colors.grey[300], // Warna latar belakang sesuai dengan latar belakang layar child: CustomPaint( size: const Size(360.0, 20), // Lebar tetap, tinggi 20 painter: _TearPainter(isTop: false), ), ); } } /// CustomPainter untuk menggambar efek sobek class _TearPainter extends CustomPainter { final bool isTop; _TearPainter({required this.isTop}); @override void paint(Canvas canvas, Size size) { final paint = Paint() ..color = Colors.white ..style = PaintingStyle.fill; final path = Path(); // Create a more interesting tear effect with random peaks and valleys final random = Random(123); // Use a fixed seed for consistent rendering final segmentWidth = size.width / 20; if (isTop) { // Start from top left path.moveTo(0, 0); // Create tear effect with randomized peaks/valleys // For top tear, peaks point upward (out of the paper) for (int i = 0; i <= 20; i++) { final x = i * segmentWidth; // Alternate between peaks and valleys final y = (i % 2 == 0) ? -(2 + random.nextDouble() * 3) // Peak pointing upward (negative Y) : 0.0; // Valley at top edge path.lineTo(x, y); } // Close the path path.lineTo(size.width, 0); path.lineTo(size.width, size.height); path.lineTo(0, size.height); path.close(); } else { // Start from bottom left path.moveTo(0, size.height); // Create tear effect with randomized peaks/valleys // For bottom tear, peaks point downward (out of the paper) for (int i = 0; i <= 20; i++) { final x = i * segmentWidth; // Alternate between peaks and valleys final y = (i % 2 == 0) ? size.height + (2 + random.nextDouble() * 3) // Peak pointing downward : size.height.toDouble(); // Valley at bottom edge path.lineTo(x, y); } // Close the path path.lineTo(size.width, size.height); path.lineTo(size.width, 0); path.lineTo(0, 0); path.close(); } canvas.drawPath(path, paint); } @override bool shouldRepaint(covariant CustomPainter oldDelegate) => false; }