Last active
August 11, 2021 03:18
-
-
Save roipeker/581f38799467bf25fbe1a6d6bfbfba69 to your computer and use it in GitHub Desktop.
Canvas drawArc slices
This file contains hidden or 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 'dart:math' as math; | |
import 'package:flutter/material.dart'; | |
double deg2rad(double deg) => deg * math.pi / 180; | |
void main() { | |
runApp(MyApp()); | |
} | |
class MyApp extends StatelessWidget { | |
@override | |
Widget build(BuildContext context) { | |
return MaterialApp( | |
theme: ThemeData.dark(), | |
home: const DemoPage(), | |
); | |
} | |
} | |
class DemoPage extends StatefulWidget { | |
const DemoPage({Key? key}) : super(key: key); | |
@override | |
_DemoPageState createState() => _DemoPageState(); | |
} | |
class _DemoPageState extends State<DemoPage> { | |
double percentGap = 0.0; | |
double numSlices = 4; | |
double offsetAngle = 0.0; | |
@override | |
Widget build(BuildContext context) { | |
return Scaffold( | |
backgroundColor: Colors.black, | |
body: Center( | |
child: SizedBox( | |
width: 400, | |
child: Column( | |
mainAxisSize: MainAxisSize.min, | |
children: [ | |
CustomPaint( | |
painter: SlicePainter( | |
gap: percentGap, | |
numSlices: numSlices.round(), | |
offsetAngle: deg2rad(offsetAngle), | |
), | |
child: Container( | |
color: Colors.white10, | |
width: 400, | |
height: 400, | |
padding: const EdgeInsets.all(16), | |
child: const Text( | |
'CIRCLE SLICES', | |
style: TextStyle( | |
fontSize: 9, | |
fontWeight: FontWeight.bold, | |
color: Colors.white30, | |
), | |
), | |
), | |
), | |
_addSlider( | |
title: 'gap: ${(percentGap * 100).toStringAsFixed(1)}%', | |
value: percentGap, | |
callback: (val) => percentGap = val, | |
min: 0.0, | |
max: 1.0, | |
), | |
_addSlider( | |
title: 'slices: ${numSlices.round()}', | |
label: 'slices ${numSlices.round()}', | |
value: numSlices, | |
callback: (val) => numSlices = val, | |
min: 1, | |
max: 32, | |
divisions: 32, | |
), | |
_addSlider( | |
title: 'start angle: ${offsetAngle.round()}°', | |
value: offsetAngle, | |
callback: (val) => offsetAngle = val, | |
min: 0, | |
max: 360, | |
), | |
], | |
), | |
), | |
), | |
); | |
} | |
Widget _addSlider({ | |
required String title, | |
String? label, | |
required double value, | |
required Function(double val) callback, | |
double min = 0.0, | |
double max = 1.0, | |
int? divisions, | |
}) { | |
return Row( | |
children: [ | |
SizedBox( | |
width: 80, | |
child: Text( | |
title.toUpperCase(), | |
style: const TextStyle( | |
fontWeight: FontWeight.w600, | |
fontSize: 9, | |
color: Colors.white54, | |
), | |
), | |
), | |
Expanded( | |
child: Slider( | |
label: label, | |
value: value, | |
onChanged: (val) { | |
callback(val); | |
setState(() {}); | |
}, | |
min: min, | |
max: max, | |
divisions: divisions, | |
), | |
), | |
], | |
); | |
} | |
} | |
class SlicePainter extends CustomPainter { | |
/// percent | |
final double gap; | |
final double offsetAngle; | |
final int numSlices; | |
SlicePainter({this.gap = 0.0, this.numSlices = 4, this.offsetAngle = 0.0}); | |
@override | |
void paint(Canvas canvas, Size size) { | |
const pi = math.pi; | |
final area = Rect.fromCircle(center: size.center(Offset.zero), radius: 100); | |
final stepSize = pi * 2 / numSlices; | |
// final separation = 10 * pi / 180; | |
final separation = stepSize * gap; | |
final fill = Paint(); | |
fill.style = PaintingStyle.stroke; | |
fill.strokeWidth = 1; | |
final colors = Colors.primaries; | |
for (var i = 0; i < numSlices; ++i) { | |
fill.color = colors[i % colors.length]; | |
final startAngle = i * stepSize + separation / 2 + offsetAngle; | |
final endAngle = stepSize - separation; | |
canvas.drawArc(area, startAngle, endAngle, true, fill); | |
} | |
} | |
@override | |
bool shouldRepaint(covariant CustomPainter oldDelegate) => true; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment