Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feature/clockwise #3

Merged
merged 2 commits into from May 6, 2020
Merged

Conversation

monsieurtanuki
Copy link
Contributor

I added a clockwise parameter for the direction of the text.

I simplified the code in the process: I had trouble understanding the concept of canvas rotation when not centered on the canvas center.
Now there's only an initial canvas translation to its center, and then multiple rotations (all based on the canvas center).

I added a `clockwise` parameter for the direction of the text.

I simplified the code in the process: I had trouble understanding the concept of canvas rotation when not centered on the canvas center.
Now there's only an initial canvas translation to its center, and then multiple rotations (all based on the canvas center).
@ookami-kb
Copy link
Owner

Hey, I've looked through your PR and I like the way you've updated the canvas rotation part 👍

Regarding the clockwise parameter, I would rather make it enum – looks more user-friendly to me.

I've also played a little bit with a code, and I propose some changes – I've mainly extracted the code that should only be done once into the constructor, and make it a bit more generic. It also can be easily generalized with this inside/outside parameter, so I've added it as well.

Please look at the proposed patch and let me know what you think:

Index: lib/src/arc_text.dart
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- lib/src/arc_text.dart	(revision 9eb454c8f755161c68369ae6474cb8e44c9568ff)
+++ lib/src/arc_text.dart	(date 1588546804263)
@@ -4,6 +4,8 @@
 import 'package:flutter/widgets.dart';
 
 enum StartAngleAlignment { start, center, end }
+enum Direction { clockwise, counterClockwise }
+enum Placement { inside, outside }
 
 class ArcText extends StatelessWidget {
   const ArcText({
@@ -13,7 +15,8 @@
     @required this.textStyle,
     this.startAngle = 0,
     this.startAngleAlignment = StartAngleAlignment.start,
-    this.clockwise = true,
+    this.direction = Direction.clockwise,
+    this.placement = Placement.outside,
   }) : super(key: key);
 
   /// Radius of the arc along which the text will be drawn.
@@ -30,57 +33,87 @@
 
   /// Text alignment around [startAngle].
   ///
-  /// - [StartAngleAlignment.start] – text will start from [startAngle]
-  /// - [StartAngleAlignment.center] – text will be centered on [startAngle]
-  /// - [StartAngleAlignment.end] – text will end on [startAngle]
+  /// - [StartAngleAlignment.start] – text will start from [startAngle].
+  /// - [StartAngleAlignment.center] – text will be centered on [startAngle].
+  /// - [StartAngleAlignment.end] – text will end on [startAngle].
   final StartAngleAlignment startAngleAlignment;
 
-  /// Text direction
-  final bool clockwise;
+  /// Text direction.
+  final Direction direction;
+
+  /// Text placement relative to circle with the same [radius].
+  final Placement placement;
 
   @override
   Widget build(BuildContext context) => CustomPaint(
         painter: _Painter(
-          radius,
-          text,
-          textStyle,
-          startAngleAlignment,
-          startAngle,
-          clockwise,
+          radius: radius,
+          text: text,
+          textStyle: textStyle,
+          alignment: startAngleAlignment,
+          initialAngle: startAngle,
+          direction: direction,
+          placement: placement,
         ),
       );
 }
 
 class _Painter extends CustomPainter {
-  _Painter(
-    this.radius,
-    this.text,
-    this.textStyle,
-    this.alignment,
-    this.initialAngle,
-    this.clockwise,
-  );
+  _Painter({
+    @required num radius,
+    @required this.text,
+    @required this.textStyle,
+    @required StartAngleAlignment alignment,
+    @required double initialAngle,
+    @required Direction direction,
+    @required Placement placement,
+  }) {
+    _textPainter.text = TextSpan(text: text, style: textStyle);
+    _textPainter.layout(minWidth: 0, maxWidth: double.maxFinite);
+
+    switch (placement) {
+      case Placement.inside:
+        this.radius = radius;
+        break;
+      case Placement.outside:
+        this.radius = radius + _textPainter.height;
+        break;
+    }
 
-  final num radius;
+    switch (direction) {
+      case Direction.clockwise:
+        angleWithAlignment = initialAngle + _getAlignmentOffset(alignment);
+        angleMultiplier = 1;
+        heightOffset = -this.radius;
+        break;
+      case Direction.counterClockwise:
+        angleWithAlignment =
+            initialAngle - _getAlignmentOffset(alignment) + math.pi;
+        angleMultiplier = -1;
+        heightOffset = this.radius - _textPainter.height;
+        break;
+    }
+  }
+
   final String text;
-  final double initialAngle;
   final TextStyle textStyle;
-  final StartAngleAlignment alignment;
-  final bool clockwise;
+  num radius;
+  int angleMultiplier;
+  double heightOffset;
+  double angleWithAlignment;
 
   final _textPainter = TextPainter(textDirection: TextDirection.ltr);
 
   @override
   void paint(Canvas canvas, Size size) {
+    canvas.save();
     canvas.translate(size.width / 2, size.height / 2);
-
-    final angleWithAlignment = clockwise ? initialAngle + _getAlignmentOffset()
-        : initialAngle + math.pi - _getAlignmentOffset();
     canvas.rotate(angleWithAlignment);
-    _drawText(canvas);
+    _drawText(canvas, angleMultiplier, heightOffset);
+    canvas.restore();
   }
 
-  double _getAlignmentOffset() {
+  double _getAlignmentOffset(StartAngleAlignment alignment) {
     switch (alignment) {
       case StartAngleAlignment.start:
         return 0;
@@ -103,14 +136,12 @@
     return finalRotation;
   }
 
-  void _drawText(Canvas canvas) {
+  void _drawText(Canvas canvas, int angleMultiplier, double heightOffset) {
     for (int i = 0; i < text.length; i++) {
       final translation = _getTranslation(text[i]);
-      final halfAngleOffset = translation.alpha / 2 * (clockwise ? 1 : -1);
+      final halfAngleOffset = translation.alpha / 2 * angleMultiplier;
       canvas.rotate(halfAngleOffset);
-      _textPainter.paint(canvas,
-          Offset(-translation.d / 2,
-              clockwise ? -radius -_textPainter.height : radius));
+      _textPainter.paint(canvas, Offset(-translation.d / 2, heightOffset));
       canvas.rotate(halfAngleOffset);
     }
   }

@ookami-kb ookami-kb merged commit 2e60224 into ookami-kb:master May 6, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants