paint method
void
paint(
- Canvas canvas,
- Size size,
- double progress,
- Offset center,
- Color color, {
- double radiusMultiplier = 1.0,
- Offset positionOffset = Offset.zero,
override
Implementation
@override
void paint(
Canvas canvas, Size size, double progress, Offset center, Color color,
{double radiusMultiplier = 1.0, Offset positionOffset = Offset.zero}) {
final adjustedCenter = center + positionOffset;
// Parameters
final double maxShredLength = size.width * 0.6 * radiusMultiplier;
// Jumlah strip kertas yang tersobek
final int stripCount = 16;
// Opacity kontrol
double opacity = 1.0;
if (progress < 0.1) {
opacity = progress / 0.1; // Fade in
} else if (progress > 0.9) {
opacity = (1.0 - progress) / 0.9; // Fade out
}
// Menggambar border outline widget (simulasi kertas)
final double paperSize = size.width * 0.5 * radiusMultiplier;
// Warna background (kertas) - lighten dari warna dasar
final Color paperColor = Color.lerp(Colors.white, color, 0.1)!;
// Rect untuk kertas (sedikit lebih kecil dari widget)
final Rect paperRect = Rect.fromCenter(
center: adjustedCenter, width: paperSize, height: paperSize);
// Style untuk kertas
final Paint paperPaint = Paint()
..color = paperColor.withOpacity(opacity * 0.9)
..style = PaintingStyle.fill;
// Menggambar kertas dengan sedikit rotasi
canvas.save();
canvas.translate(adjustedCenter.dx, adjustedCenter.dy);
canvas.rotate(math.pi / 16); // Slight tilt
canvas.translate(-adjustedCenter.dx, -adjustedCenter.dy);
canvas.drawRect(paperRect, paperPaint);
// Menggambar outline
canvas.drawRect(
paperRect,
Paint()
..color = color.withOpacity(opacity * 0.7)
..style = PaintingStyle.stroke
..strokeWidth = 1.0);
// Random untuk konsistensi
final math.Random random = math.Random(42);
// Menggambar shredding effect
for (int i = 0; i < stripCount; i++) {
// Random seed untuk strip ini
final int stripSeed = i * 100;
final random = math.Random(stripSeed);
// ... continuing PaperShredAnimator
// Posisi strip di tepi kertas
final double normalizedPos = i / (stripCount - 1);
// Pilih tepi mana yang tersobek (top, right, bottom, left)
int edgeSide;
if (i < stripCount / 4) {
edgeSide = 0; // Top
} else if (i < stripCount / 2) {
edgeSide = 1; // Right
} else if (i < 3 * stripCount / 4) {
edgeSide = 2; // Bottom
} else {
edgeSide = 3; // Left
}
// Offset dalam edge berdasarkan posisi
final double edgeNormalizedPos = (normalizedPos * 4) % 1.0;
// Start point pada tepi kertas
Offset startPoint;
double shredAngle; // Sudut sobekan
switch (edgeSide) {
case 0: // Top edge
startPoint = Offset(
paperRect.left + paperRect.width * edgeNormalizedPos,
paperRect.top);
shredAngle =
math.pi / 2 + (random.nextDouble() * math.pi / 4 - math.pi / 8);
break;
case 1: // Right edge
startPoint = Offset(paperRect.right,
paperRect.top + paperRect.height * edgeNormalizedPos);
shredAngle =
math.pi + (random.nextDouble() * math.pi / 4 - math.pi / 8);
break;
case 2: // Bottom edge
startPoint = Offset(
paperRect.right - paperRect.width * edgeNormalizedPos,
paperRect.bottom);
shredAngle = 3 * math.pi / 2 +
(random.nextDouble() * math.pi / 4 - math.pi / 8);
break;
case 3: // Left edge
startPoint = Offset(paperRect.left,
paperRect.bottom - paperRect.height * edgeNormalizedPos);
shredAngle = 0 + (random.nextDouble() * math.pi / 4 - math.pi / 8);
break;
default:
startPoint = Offset(paperRect.left, paperRect.top);
shredAngle = 0;
}
// Menghitung panjang sobekan berdasarkan progress
// Muncul dengan cepat lalu stabil
double shredProgress = progress < 0.4
? progress / 0.4
: // Cepat di awal
1.0; // Stabil setelahnya
// Panjang strip
final double stripLength =
maxShredLength * shredProgress * (0.5 + random.nextDouble() * 0.5);
// End point setelah sobekan
final Offset endPoint = Offset(
startPoint.dx + math.cos(shredAngle) * stripLength,
startPoint.dy + math.sin(shredAngle) * stripLength);
// Lebar strip
final double stripWidth = 2.0 + random.nextDouble() * 3.0;
// Path untuk strip
final Path stripPath = Path();
// Bentuk irregular untuk strip
// Jalur zig-zag untuk sobekan kertas yang tidak rata
stripPath.moveTo(startPoint.dx, startPoint.dy);
// Jumlah segment zigzag
final int zigzagCount = (stripLength / 10).round().clamp(3, 8);
// Garis pertama lurus dari tepi
final double straightLength = stripLength * 0.1;
Offset currentPoint = Offset(
startPoint.dx + math.cos(shredAngle) * straightLength,
startPoint.dy + math.sin(shredAngle) * straightLength);
stripPath.lineTo(currentPoint.dx, currentPoint.dy);
// Menggambar zigzag
for (int z = 1; z <= zigzagCount; z++) {
final double segmentT = z / zigzagCount;
// Posisi pada garis lurus
final double baseX =
startPoint.dx + (endPoint.dx - startPoint.dx) * segmentT;
final double baseY =
startPoint.dy + (endPoint.dy - startPoint.dy) * segmentT;
// Vector perpendicular untuk zigzag
final double perpX = -math.sin(shredAngle);
final double perpY = math.cos(shredAngle);
// Zigzag offset - alternate directions
final double zigzagWidth = stripWidth * (1.0 + random.nextDouble());
final double offset = (z % 2 == 0 ? 1 : -1) * zigzagWidth;
// Final point dengan zigzag offset
final Offset zigzagPoint =
Offset(baseX + perpX * offset, baseY + perpY * offset);
stripPath.lineTo(zigzagPoint.dx, zigzagPoint.dy);
currentPoint = zigzagPoint;
}
// Memastikan akhir path mencapai endpoint
stripPath.lineTo(endPoint.dx, endPoint.dy);
// Menghitung titik kontrol untuk shadow jagged edge
final List<Offset> jaggies = [];
for (int j = 0; j <= 6; j++) {
final double jT = j / 6.0;
// Posisi pada garis
final double jX = startPoint.dx + (endPoint.dx - startPoint.dx) * jT;
final double jY = startPoint.dy + (endPoint.dy - startPoint.dy) * jT;
// Perpendicular vector
final double jPerpX = -math.sin(shredAngle);
final double jPerpY = math.cos(shredAngle);
// Random offset perpendicular
final double jOffset = (random.nextDouble() * 2 - 1) * stripWidth;
jaggies.add(Offset(jX + jPerpX * jOffset, jY + jPerpY * jOffset));
}
// Menggambar tepi sobek dengan shadow
final Path shadowPath = Path();
shadowPath.moveTo(startPoint.dx, startPoint.dy);
// Menambahkan semua titik-titik jagged
for (int j = 0; j < jaggies.length; j++) {
shadowPath.lineTo(jaggies[j].dx, jaggies[j].dy);
}
// Menggambar shadow
canvas.drawPath(
shadowPath,
Paint()
..color = Colors.black.withOpacity(opacity * 0.2)
..style = PaintingStyle.stroke
..strokeWidth = 1.0
..maskFilter = MaskFilter.blur(BlurStyle.normal, 2.0));
// Menggambar strip dengan warna kertas
canvas.drawPath(
stripPath,
Paint()
..color = paperColor.withOpacity(opacity)
..style = PaintingStyle.stroke
..strokeWidth = stripWidth
..strokeCap = StrokeCap.round);
// Edge highlight
canvas.drawPath(
stripPath,
Paint()
..color = color.withOpacity(opacity * 0.3)
..style = PaintingStyle.stroke
..strokeWidth = 0.5);
}
canvas.restore();
}