draw method
Implementation
@override
void draw(
Canvas canvas,
SpoilerContext context,
) {
final isFading = context.isFading;
final fadeRadius = context.fadeRadius;
final fadeCenter = context.fadeCenter;
final fadeEdgeThickness = context.config.fadeConfig?.edgeThickness ?? 1;
_maxParticleSize = context.config.particleConfig.maxParticleSize;
_particleColor = context.config.particleConfig.color;
_particleSpeed = context.config.particleConfig.speed;
final count = _particles.length;
if (count == 0) return;
_reallocBuffers(count);
final transforms = _valTransforms!;
final rects = _valRects!;
final colors = _valColors!;
final spriteRadius = _circleImage.dimension * 0.5;
final bounds = context.spoilerBounds;
final boundaryFadePx = max(spriteRadius * 3.0, 6.0);
double smoothstep(double edge0, double edge1, double x) {
final t = ((x - edge0) / (edge1 - edge0)).clamp(0.0, 1.0);
return t * t * (3.0 - 2.0 * t);
}
int index = 0;
for (final p in _particles) {
final transformIndex = index * 4;
final lifeScale = _lifeSizeMin + (1.0 - _lifeSizeMin) * p.life;
final edgeDist = min(
min(p.dx - bounds.left, bounds.right - p.dx),
min(p.dy - bounds.top, bounds.bottom - p.dy),
);
final edgeFade =
edgeDist <= 0.0 ? 0.0 : smoothstep(0.0, boundaryFadePx, edgeDist);
final particleRadius = max(spriteRadius * lifeScale, 0.0001);
final edgeClamp = (edgeDist / particleRadius).clamp(0.0, 1.0);
final edgeScale = edgeFade * edgeClamp;
if (isFading) {
final distSq = (fadeCenter - p).distanceSquared;
final radiusSq = fadeRadius * fadeRadius;
if (distSq < radiusSq) {
final dist = sqrt(distSq);
final scale = (dist > fadeRadius - fadeEdgeThickness) ? 1.5 : 1.0;
final color =
(dist > fadeRadius - fadeEdgeThickness) ? Colors.white : p.color;
final scaled = scale * lifeScale * edgeScale;
final edgeColor = color.withValues(alpha: color.a * edgeScale);
transforms[transformIndex + 0] = scaled;
transforms[transformIndex + 1] = 0.0;
transforms[transformIndex + 2] = p.dx - spriteRadius * scaled;
transforms[transformIndex + 3] = p.dy - spriteRadius * scaled;
rects[transformIndex + 0] = 0.0;
rects[transformIndex + 1] = 0.0;
rects[transformIndex + 2] = _circleImage.dimension.toDouble();
rects[transformIndex + 3] = _circleImage.dimension.toDouble();
colors[index] = edgeScale > 0.0
? _colorToArgb(edgeColor)
: _colorToArgb(Colors.transparent);
if (edgeScale <= 0.0) {
transforms[transformIndex + 0] = 0.0;
}
index++;
} else {
// outside fade circle
colors[index] = _colorToArgb(Colors.transparent);
transforms[transformIndex + 0] = 0;
index++;
}
} else {
// normal
final scaled = lifeScale * edgeScale;
transforms[transformIndex + 0] = scaled;
transforms[transformIndex + 1] = 0.0;
transforms[transformIndex + 2] = p.dx - spriteRadius * scaled;
transforms[transformIndex + 3] = p.dy - spriteRadius * scaled;
rects[transformIndex + 0] = 0.0;
rects[transformIndex + 1] = 0.0;
rects[transformIndex + 2] = _circleImage.dimension.toDouble();
rects[transformIndex + 3] = _circleImage.dimension.toDouble();
final edgeColor = p.color.withValues(alpha: p.color.a * edgeScale);
colors[index] = edgeScale > 0.0
? _colorToArgb(edgeColor)
: _colorToArgb(Colors.transparent);
if (edgeScale <= 0.0) {
transforms[transformIndex + 0] = 0.0;
}
index++;
}
}
if (index > 0) {
canvas.drawRawAtlas(
_circleImage.image,
transforms,
rects,
colors,
BlendMode.modulate,
null,
_particlePaint,
);
}
}