Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save mogaming217/44df5aadf85d0f8427ec334379f72b20 to your computer and use it in GitHub Desktop.
Save mogaming217/44df5aadf85d0f8427ec334379f72b20 to your computer and use it in GitHub Desktop.
[Flutter] グラデーションでのCircularProgressIndicator(くるくる回るやつじゃなく0〜100%を円で表示するやつ)
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'dart:math';
// CustomColorは適宜置き換えてください
double degreeToRadian(double degree) => degree * pi / 180;
class GradientCircularProgressIndicator extends HookConsumerWidget {
const GradientCircularProgressIndicator({
super.key,
required this.progress,
required this.size,
this.gradientColors = CustomColor.gradientColors,
this.strokeWidth = 2,
this.animationDuration = const Duration(seconds: 1),
});
/// 0 - 1
final double progress;
final Size size;
final List<Color> gradientColors;
final double strokeWidth;
final Duration animationDuration;
@override
Widget build(BuildContext context, WidgetRef ref) {
final controller = useAnimationController(duration: animationDuration);
final preProgress = useState(0.0);
useEffect(() {
controller.forward(from: preProgress.value / progress);
preProgress.value = progress;
return null;
}, [progress]);
return AnimatedBuilder(
animation: controller,
builder: (context, child) => CustomPaint(
painter: _Painter(
gradientColors: gradientColors,
backgroundStrokeColor: CustomColor.whiteAlpha400,
strokeWidth: strokeWidth,
animationProgress: controller.value,
progressEnd: progress,
),
size: size,
),
);
}
}
class _Painter extends CustomPainter {
_Painter({
required this.gradientColors,
required this.backgroundStrokeColor,
required this.strokeWidth,
required this.animationProgress,
required this.progressEnd,
});
final List<Color> gradientColors;
final Color backgroundStrokeColor;
final double strokeWidth;
final double animationProgress;
/// 0 - 1
final double progressEnd;
final double baseStartAngle = -90;
@override
void paint(Canvas canvas, Size size) {
final radius = (size.width - strokeWidth) / 2;
final center = Offset(size.width / 2, size.height / 2);
final backgroundPaint = Paint()
..isAntiAlias = true
..strokeWidth = strokeWidth
..color = backgroundStrokeColor
..style = PaintingStyle.stroke;
// 4. draw a circle
canvas.drawCircle(center, radius, backgroundPaint);
if (progressEnd > 0) {
final foregroundPaint = Paint()
..isAntiAlias = true
..style = PaintingStyle.stroke
..strokeWidth = strokeWidth;
foregroundPaint.shader = SweepGradient(
colors: gradientColors,
tileMode: TileMode.repeated,
startAngle: degreeToRadian(0),
endAngle: degreeToRadian(360 * progressEnd),
transform: GradientRotation(degreeToRadian(-90)),
).createShader(
Rect.fromCircle(center: center, radius: 0),
);
double startAngle = degreeToRadian(baseStartAngle);
double sweepAngle = degreeToRadian(animationProgress * progressEnd * 360);
canvas.drawArc(Rect.fromCircle(center: center, radius: radius), startAngle, sweepAngle, false, foregroundPaint);
}
}
@override
bool shouldRepaint(_Painter oldDelegate) => oldDelegate.animationProgress != animationProgress;
}
@mogaming217
Copy link
Author

実装したけど結局使わなくなったので供養 🙏

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment