Created
March 16, 2024 08:18
-
-
Save alwerr/9388c95f67f3dbd7bf3a829a833bd59a to your computer and use it in GitHub Desktop.
The full code , I just want to know what color is under the black cube when or after the user spins the wheel
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import 'package:flutter/material.dart'; | |
import 'dart:math'; | |
class MyWidget extends StatelessWidget { | |
const MyWidget({super.key}); | |
@override | |
Widget build(BuildContext context) { | |
return Scaffold( | |
body: Stack( | |
alignment: Alignment.center, | |
children: [ | |
Positioned( | |
bottom: 40, | |
child: Pie( | |
onTap: () {}, | |
onSpin: (p0) {}, | |
), | |
), | |
Positioned( | |
top: 180, | |
child: Container( | |
width: 30, | |
height: 30, | |
color: Colors.black, | |
), | |
), | |
], | |
), | |
); | |
} | |
} | |
class Pie extends StatefulWidget { | |
const Pie({super.key, required this.onSpin, required this.onTap}); // changed | |
final Function() onTap; | |
final Function(double) onSpin; | |
@override | |
PieState createState() => PieState(); | |
} | |
class PieState extends State<Pie> { | |
double finalAngle = 0.0; | |
double oldAngle = 0.0; | |
double upsetAngle = 0.0; | |
@override | |
Widget build(BuildContext context) { | |
return _defaultApp(context); | |
} | |
_defaultApp(BuildContext context) { | |
return SizedBox( | |
width: 300, | |
height: 300, | |
child: LayoutBuilder( | |
builder: (context, constraints) { | |
Offset centerOfGestureDetector = Offset(constraints.maxWidth / 2, constraints.maxHeight / 2); | |
return GestureDetector( | |
behavior: HitTestBehavior.translucent, | |
onTap: widget.onTap, | |
onPanStart: (details) { | |
final touchPositionFromCenter = details.localPosition - centerOfGestureDetector; | |
upsetAngle = oldAngle - touchPositionFromCenter.direction; | |
}, | |
onPanEnd: (details) { | |
setState( | |
() { | |
oldAngle = finalAngle; | |
}, | |
); | |
}, | |
onPanUpdate: (details) { | |
final touchPositionFromCenter = details.localPosition - centerOfGestureDetector; | |
setState( | |
() { | |
finalAngle = touchPositionFromCenter.direction + upsetAngle; | |
}, | |
); | |
widget.onSpin(finalAngle); | |
}, | |
child: Transform.rotate( | |
angle: finalAngle, | |
child: const PieChart( | |
data: [30, 30, 30], | |
customColours: [Colors.amber, Colors.red, Colors.purple], | |
labels: ['a', 'b', 'c'], | |
textStyle: TextStyle(), | |
), | |
), | |
); | |
}, | |
), | |
); | |
} | |
} | |
class PieChart extends StatelessWidget { | |
final List<double> data; | |
final List<String> labels; | |
final double angleOffset; | |
final double radius; | |
final List<Color> customColours; | |
final TextStyle textStyle; | |
const PieChart({ | |
super.key, | |
required this.data, | |
required this.labels, | |
required this.customColours, | |
required this.textStyle, | |
this.angleOffset = 0, | |
this.radius = 100, | |
}); | |
@override | |
Widget build(BuildContext context) { | |
double total = data.fold(0, (previousValue, element) => previousValue + element); | |
final startAngle = 0 - pi / 2 + angleOffset; | |
return CustomPaint( | |
painter: _PieChartPainter( | |
data, | |
labels, | |
total, | |
startAngle, | |
customColours, | |
textStyle, | |
), | |
size: Size.fromRadius(radius), | |
); | |
} | |
} | |
class _PieChartPainter extends CustomPainter { | |
final List<double> data; | |
final List<String> labels; | |
final double total; | |
final double startAngle; | |
final List<Color> customColours; | |
final TextStyle textStyle; | |
_PieChartPainter( | |
this.data, | |
this.labels, | |
this.total, | |
this.startAngle, | |
this.customColours, | |
this.textStyle, | |
); | |
@override | |
void paint(Canvas canvas, Size size) { | |
final center = Offset(size.width / 2, size.height / 2); | |
final radius = min(size.width, size.height) / 2; | |
final rect = Rect.fromCircle(center: center, radius: radius); | |
final paint = Paint()..style = PaintingStyle.fill; | |
double sweepAngle = 0; | |
for (int i = 0; i < data.length; i++) { | |
final ratio = data[i] / total; | |
final sweepRad = ratio * 2 * pi; | |
paint.color = _getColor(i); | |
canvas.drawArc(rect, startAngle + sweepAngle, sweepRad, true, paint); | |
final labelAngle = startAngle + sweepAngle + sweepRad / 2; | |
final labelX = center.dx + (radius * 0.6) * cos(labelAngle); | |
final labelY = center.dy + (radius * 0.6) * sin(labelAngle); | |
final labelOffset = Offset(labelX, labelY); | |
_drawLabel(canvas, labels[i], labelOffset); | |
sweepAngle += sweepRad; | |
} | |
} | |
void _drawLabel(Canvas canvas, String label, Offset offset) { | |
final textSpan = TextSpan( | |
text: label, | |
style: textStyle, | |
); | |
final textPainter = TextPainter( | |
text: textSpan, | |
textDirection: TextDirection.ltr, | |
); | |
textPainter.layout(); | |
final textOffset = Offset(offset.dx - textPainter.width / 2, offset.dy - textPainter.height / 2); | |
textPainter.paint(canvas, textOffset); | |
} | |
Color _getColor(int index) { | |
return customColours[index % customColours.length]; | |
} | |
@override | |
bool shouldRepaint(_PieChartPainter oldDelegate) { | |
return oldDelegate.data != data || | |
oldDelegate.labels != labels || | |
oldDelegate.total != total || | |
oldDelegate.startAngle != startAngle; | |
} | |
} | |
void main() { | |
runApp(const MyApp()); | |
} | |
class MyApp extends StatelessWidget { | |
const MyApp({super.key}); | |
// This widget is the root of your application. | |
@override | |
Widget build(BuildContext context) { | |
return MaterialApp( | |
title: 'Flutter Demo', | |
theme: ThemeData( | |
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple), | |
useMaterial3: true, | |
), | |
home: const MyWidget(), | |
); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment