paint method
void
paint(
- Canvas cv,
- Size size,
- double progress,
- Offset center,
- Color color, {
- double radiusMultiplier = 1.0,
- Offset positionOffset = Offset.zero,
override
Implementation
@override
void paint(Canvas cv, Size size, double progress, Offset center, Color color,
{double radiusMultiplier = 1.0, Offset positionOffset = Offset.zero}) {
final c = center + positionOffset;
final rnd = math.Random(42);
final minSide = math.min(size.width, size.height);
final spawnRadius = minSide * spawnScale * radiusMultiplier;
// sudut partikel (deterministik)
final angles = List<double>.generate(
particleCount,
(i) => useUniformAngle
? (i / particleCount) * 2 * math.pi
: rnd.nextDouble() * 2 * math.pi,
);
for (int i = 0; i < particleCount; i++) {
// delay ringan antar partikel
final delay = i * 0.02;
final rawT = progress - delay;
if (rawT <= 0) continue;
// normalisasi agar setiap partikel selesai di progress==1
final t = (rawT / (1 - delay)).clamp(0.0, 1.0);
final angle = angles[i];
// ─── posisi radial ───
double dist;
if (t < _tailRetractEnd) {
dist = spawnRadius; // tetap di tepi
} else {
final tt = (t - _tailRetractEnd) / (1 - _tailRetractEnd); // 0‑1
dist = spawnRadius * (1 - _easeInQuad(tt)); // implosion
}
final pos = c + Offset(math.cos(angle), math.sin(angle)) * dist;
// ─── tail length ───
double tailLen;
if (t < _tailRetractEnd) {
final tailT = 1 - (t / _tailRetractEnd); // 1→0
tailLen = circleRadius * tailFactor * tailT * radiusMultiplier;
} else {
tailLen = 0;
}
// ─── skala & opasitas dot ───
final scale = t < _tailRetractEnd
? 1.0
: 1 -
((t - _tailRetractEnd) / (1 - _tailRetractEnd)) *
.4; // sedikit mengecil
final opacity = t < _tailRetractEnd
? 1.0
: 1 - ((t - _tailRetractEnd) / (1 - _tailRetractEnd)); // fade out
// ─── warna ───
Color col = color;
if (enableHueTilt) {
final hsl = HSLColor.fromColor(color);
final hueShift = (angle / (2 * math.pi)) * 360 * hueTiltRange;
col = hsl
.withHue((hsl.hue + hueShift) % 360)
.withSaturation((hsl.saturation * saturationBoost).clamp(0.0, 1.0))
.toColor();
}
col = col.withOpacity(opacity.toDouble());
// ─── gambar dot ───
final rad = circleRadius * radiusMultiplier * scale;
cv.drawCircle(pos, rad, Paint()..color = col);
// ─── gambar tail (jika masih ada) ───
if (tailLen > 0) {
final tailEnd =
pos + Offset(math.cos(angle), math.sin(angle)) * tailLen;
cv.drawLine(
pos,
tailEnd,
Paint()
..color = col
..strokeWidth = rad * .8
..strokeCap = StrokeCap.round);
}
}
}