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

Enhancement! Help in 5 smiley option #3

Open
mohdtaha60 opened this issue Apr 18, 2021 · 0 comments
Open

Enhancement! Help in 5 smiley option #3

mohdtaha60 opened this issue Apr 18, 2021 · 0 comments
Labels
enhancement New feature or request

Comments

@mohdtaha60
Copy link

mohdtaha60 commented Apr 18, 2021

I had a requirement where i needed 5 smileys. I tried my best but it's still having issues where the ArcSelector is not working properly. Can you please help me and guide me?

Code is as follows

ArcChooser.dart
`
import 'dart:math';
import 'dart:ui';

import 'package:flutter/material.dart';
import 'package:flutter/painting.dart';

class ArcChooser extends StatefulWidget {
late ArcSelectedCallback arcSelectedCallback;

@OverRide
State createState() {
return ChooserState(arcSelectedCallback);
}
}

class ChooserState extends State
with SingleTickerProviderStateMixin {
var slideValue = 200;
Offset? centerPoint;

double userAngle = 0.0;

double? startAngle;

static double center = 270.0;
static double centerInRadians = degreeToRadians(center);
static double angle = 45.0;

static double angleInRadians = degreeToRadians(angle);
static double angleInRadiansByTwo = angleInRadians / 2;
static double centerItemAngle = degreeToRadians(center - (angle / 2));
late List arcItems;

late AnimationController animation;
double? animationStart;
double animationEnd = 0.0;

int currentPosition = 0;

Offset? startingPoint;
Offset? endingPoint;

late ArcSelectedCallback arcSelectedCallback;

ChooserState(ArcSelectedCallback arcSelectedCallback) {
this.arcSelectedCallback = arcSelectedCallback;
}

static double degreeToRadians(double degree) {
return degree * (pi / 180);
}

static double radianToDegrees(double radian) {
return radian * (180 / pi);
}

@OverRide
void initState() {
arcItems = List.empty(growable: true);

arcItems.add(ArcItem("OK", [Color(0xFF21e1fa), Color(0xff3bb8fd)],
    angleInRadiansByTwo + userAngle));
arcItems.add(ArcItem("Better", [Color(0xFF2EA44F), Color(0xFF41f7c7)],
    angleInRadiansByTwo + userAngle + (angleInRadians)));
arcItems.add(ArcItem("GOOD", [Color(0xFF3ee98a), Color(0xFF41f7c7)],
    angleInRadiansByTwo + userAngle + (2 * angleInRadians)));
arcItems.add(ArcItem("BADD", [Color(0xFFfe0944), Color(0xFFfeae96)],
    angleInRadiansByTwo + userAngle + (3 * angleInRadians)));
arcItems.add(ArcItem("UGH", [Color(0xFFF9D976), Color(0xfff39f86)],
    angleInRadiansByTwo + userAngle + (4 * angleInRadians)));
arcItems.add(ArcItem("OK", [Color(0xFF21e1fa), Color(0xff3bb8fd)],
    angleInRadiansByTwo + userAngle + (5 * angleInRadians)));
arcItems.add(ArcItem("Better", [Color(0xFF2EA44F), Color(0xFF41f7c7)],
    angleInRadiansByTwo + userAngle + (6 * angleInRadians)));
arcItems.add(ArcItem("GOOD", [Color(0xFF3ee98a), Color(0xFF41f7c7)],
    angleInRadiansByTwo + userAngle + (7 * angleInRadians)));
arcItems.add(ArcItem("BAD2", [Color(0xFFfe0944), Color(0xFFfeae96)],
    angleInRadiansByTwo + userAngle + (8 * angleInRadians)));
arcItems.add(ArcItem("UGH", [Color(0xFFF9D976), Color(0xfff39f86)],
    angleInRadiansByTwo + userAngle + (8 * angleInRadians)));
animation = new AnimationController(
    duration: const Duration(milliseconds: 200), vsync: this);
animation.addListener(() {
  userAngle = lerpDouble(animationStart, animationEnd, animation.value)!;
  setState(() {
    for (int i = 0; i < arcItems.length; i++) {
      arcItems[i].startAngle =
          angleInRadiansByTwo + userAngle + (i * angleInRadians);
    }
  });
});
super.initState();

}

@OverRide
Widget build(BuildContext context) {
double centerX = MediaQuery.of(context).size.width / 2;
double centerY = MediaQuery.of(context).size.height * 1.5;
centerPoint = Offset(centerX, centerY);

return new GestureDetector(

// onTap: () {
// print('ChooserState.build ONTAP');
// animationStart = touchAngle;
// animationEnd = touchAngle + angleInRadians;
// animation.forward(from: 0.0);
// },
onPanStart: (DragStartDetails details) {
startingPoint = details.globalPosition;
var deltaX = centerPoint!.dx - details.globalPosition.dx;
var deltaY = centerPoint!.dy - details.globalPosition.dy;
startAngle = atan2(deltaY, deltaX);
},
onPanUpdate: (DragUpdateDetails details) {
endingPoint = details.globalPosition;
var deltaX = centerPoint!.dx - details.globalPosition.dx;
var deltaY = centerPoint!.dy - details.globalPosition.dy;
var freshAngle = atan2(deltaY, deltaX);
userAngle += freshAngle - startAngle!;
setState(() {
for (int i = 0; i < arcItems.length; i++) {
arcItems[i].startAngle =
angleInRadiansByTwo + userAngle + (i * angleInRadians);
}
});
startAngle = freshAngle;
},
onPanEnd: (DragEndDetails details) {
//find top arc item with Magic!!
bool rightToLeft = startingPoint!.dx < endingPoint!.dx;

// Animate it from this values
animationStart = userAngle;
if (rightToLeft) {
animationEnd += angleInRadians;
currentPosition--;
if (currentPosition < 0) {
currentPosition = arcItems.length - 1;
}
} else {
animationEnd -= angleInRadians;
currentPosition++;
if (currentPosition >= arcItems.length) {
currentPosition = 0;
}
}

    if (arcSelectedCallback != null) {
      arcSelectedCallback(
          currentPosition,
          arcItems[(currentPosition >= (arcItems.length - 1))
              ? 0
              : currentPosition + 1]);
    }

    animation.forward(from: 0.0);
  },
  child: CustomPaint(
    size: Size(MediaQuery.of(context).size.width,
        MediaQuery.of(context).size.width * 1 / 1.5),
    painter: ChooserPainter(arcItems, angleInRadians),
  ),
);

}
}

// draw the arc and other stuff
class ChooserPainter extends CustomPainter {
//debugging Paint
final debugPaint = new Paint()
..color = Colors.red.withAlpha(100) //0xFFF9D976
..strokeWidth = 1.0
..style = PaintingStyle.stroke;

final linePaint = new Paint()
..color = Colors.black.withAlpha(65) //0xFFF9D976
..strokeWidth = 2.0
..style = PaintingStyle.stroke
..strokeCap = StrokeCap.square;

final whitePaint = new Paint()
..color = Colors.white //0xFFF9D976
..strokeWidth = 1.0
..style = PaintingStyle.fill;

late List arcItems;
late double angleInRadians;
late double angleInRadiansByTwo;
late double angleInRadians1;
late double angleInRadians2;
late double angleInRadians3;
late double angleInRadians4;

ChooserPainter(List arcItems, double angleInRadians) {
this.arcItems = arcItems;
this.angleInRadians = angleInRadians;
this.angleInRadiansByTwo = angleInRadians / 2;

angleInRadians1 = angleInRadians / 6;
angleInRadians2 = angleInRadians / 3;
angleInRadians3 = angleInRadians * 4 / 6;
angleInRadians4 = angleInRadians * 5 / 6;

}

@OverRide
void paint(Canvas canvas, Size size) {
//common calc
double centerX = size.width / 2;
double centerY = size.height * 1.6;
Offset center = Offset(centerX, centerY);
double radius = sqrt((size.width * size.width) / 2);

// var mainRect = Rect.fromLTRB(0.0, 0.0, size.width, size.height);
// canvas.drawRect(mainRect, debugPaint);

//for white arc at bottom
double leftX = centerX - radius;
double topY = centerY - radius;
double rightX = centerX + radius;
double bottomY = centerY + radius;

//for items
double radiusItems = radius * 1.5;
double leftX2 = centerX - radiusItems;
double topY2 = centerY - radiusItems;
double rightX2 = centerX + radiusItems;
double bottomY2 = centerY + radiusItems;

//for shadow
double radiusShadow = radius * 1.13;
double leftX3 = centerX - radiusShadow;
double topY3 = centerY - radiusShadow;

double rightX3 = centerX + radiusShadow;
double bottomY3 = centerY + radiusShadow;

double radiusText = radius * 1.30;
double radius4 = radius * 1.12;
double radius5 = radius * 1.06;
var arcRect = Rect.fromLTRB(leftX2, topY2, rightX2, bottomY2);

var dummyRect = Rect.fromLTRB(0.0, 0.0, size.width, size.height);

canvas.clipRect(dummyRect, clipOp: ClipOp.intersect);

for (int i = 0; i < arcItems.length; i++) {
  canvas.drawArc(
      arcRect,
      arcItems[i].startAngle,
      angleInRadians,
      true,
      new Paint()
        ..style = PaintingStyle.fill
        ..shader = new LinearGradient(
          colors: arcItems[i].colors,
        ).createShader(dummyRect));

  //Draw text
  TextSpan span = new TextSpan(
      style: new TextStyle(
          fontWeight: FontWeight.normal,
          fontSize: 32.0,
          color: Colors.white),
      text: arcItems[i].text);
  TextPainter tp = new TextPainter(
    text: span,
    textAlign: TextAlign.center,
    textDirection: TextDirection.ltr,
  );
  tp.layout();

  //find additional angle to make text in center
  double f = tp.width / 2;
  double t = sqrt((radiusText * radiusText) + (f * f));

  double additionalAngle = acos(
      ((t * t) + (radiusText * radiusText) - (f * f)) /
          (2 * t * radiusText));

  double tX = center.dx +
      radiusText *
          cos(arcItems[i].startAngle +
              angleInRadiansByTwo -
              additionalAngle); // - (tp.width/2);
  double tY = center.dy +
      radiusText *
          sin(arcItems[i].startAngle +
              angleInRadiansByTwo -
              additionalAngle); // - (tp.height/2);

  canvas.save();
  canvas.translate(tX, tY);

// canvas.rotate(arcItems[i].startAngle + angleInRadiansByTwo);
canvas.rotate(arcItems[i].startAngle +
angleInRadians +
angleInRadians +
angleInRadiansByTwo);
tp.paint(canvas, new Offset(0.0, 0.0));
canvas.restore();

  //big lines
  canvas.drawLine(
      new Offset(center.dx + radius4 * cos(arcItems[i].startAngle),
          center.dy + radius4 * sin(arcItems[i].startAngle)),
      center,
      linePaint);

  canvas.drawLine(
      new Offset(
          center.dx +
              radius4 * cos(arcItems[i].startAngle + angleInRadiansByTwo),
          center.dy +
              radius4 * sin(arcItems[i].startAngle + angleInRadiansByTwo)),
      center,
      linePaint);

  //small lines
  canvas.drawLine(
      new Offset(
          center.dx +
              radius5 * cos(arcItems[i].startAngle + angleInRadians1),
          center.dy +
              radius5 * sin(arcItems[i].startAngle + angleInRadians1)),
      center,
      linePaint);

  canvas.drawLine(
      new Offset(
          center.dx +
              radius5 * cos(arcItems[i].startAngle + angleInRadians2),
          center.dy +
              radius5 * sin(arcItems[i].startAngle + angleInRadians2)),
      center,
      linePaint);

  canvas.drawLine(
      new Offset(
          center.dx +
              radius5 * cos(arcItems[i].startAngle + angleInRadians3),
          center.dy +
              radius5 * sin(arcItems[i].startAngle + angleInRadians3)),
      center,
      linePaint);

  canvas.drawLine(
      new Offset(
          center.dx +
              radius5 * cos(arcItems[i].startAngle + angleInRadians4),
          center.dy +
              radius5 * sin(arcItems[i].startAngle + angleInRadians4)),
      center,
      linePaint);
}

//shadow
Path shadowPath = new Path();
shadowPath.addArc(
    Rect.fromLTRB(leftX3, topY3, rightX3, bottomY3),
    ChooserState.degreeToRadians(180.0),
    ChooserState.degreeToRadians(180.0));
canvas.drawShadow(shadowPath, Colors.black, 18.0, true);

//bottom white arc
canvas.drawArc(
    Rect.fromLTRB(leftX, topY, rightX, bottomY),
    ChooserState.degreeToRadians(180.0),
    ChooserState.degreeToRadians(180.0),
    true,
    whitePaint);

}

@OverRide
bool shouldRepaint(CustomPainter oldDelegate) {
return true;
}
}

typedef void ArcSelectedCallback(int position, ArcItem arcitem);

class ArcItem {
String text;
List colors;
double startAngle;

ArcItem(this.text, this.colors, this.startAngle);
}
`

smiley.dart
`import 'dart:ui';

import 'package:flutter/material.dart';

class SmilePainter extends CustomPainter {
//debugging Paint
final debugPaint = new Paint()
..color = Colors.grey //0xFFF9D976
..strokeWidth = 1.0
..style = PaintingStyle.stroke;

final whitePaint = new Paint()
..color = Colors.white //0xFFF9D976
..style = PaintingStyle.fill;

int slideValue = 200;

ReviewState? badReview;
ReviewState? ughReview;
ReviewState? okReview;
ReviewState? betterReview;

ReviewState? goodReview;

double? centerCenter;
double? leftCenter;
double? rightCenter;

double? smileHeight;
double? halfWidth;
double? halfHeight;

double? radius;

double? diameter;
double? startingY;
double? startingX;

double? endingX;
double? endingY;

double? oneThirdOfDia;

double? oneThirdOfDiaByTwo;

double? eyeRadius;

double? eyeRadiusbythree;

double? eyeRadiusbytwo;

SmilePainter(int slideValue) : slideValue = slideValue;

Size? lastSize;

ReviewState? currentState;

@OverRide
void paint(Canvas canvas, Size size) {
if (size != lastSize) {
lastSize = size;

  smileHeight = size.width / 2;
  halfWidth = size.width / 2;
  halfHeight = smileHeight! / 2;

  radius = 0.0;
  eyeRadius = 10.0;
  if (smileHeight! < size.width) {
    radius = halfHeight! - 16.0;
  } else {
    radius = halfWidth! - 16.0;
  }
  eyeRadius = radius! / 6.5;
  eyeRadiusbythree = eyeRadius! / 3;
  eyeRadiusbytwo = eyeRadius! / 2;

  diameter = radius! * 2;
  //left top corner
  startingX = halfWidth! - radius!;
  startingY = halfHeight! - radius!;

  oneThirdOfDia = (diameter! / 3);
  oneThirdOfDiaByTwo = oneThirdOfDia! / 2;

  //bottom right corner
  endingX = halfWidth! + radius!;
  endingY = halfHeight! + radius!;

  final leftSmileX = startingX! + (radius! / 2);

  badReview = ReviewState(
      Offset(leftSmileX, endingY! - (oneThirdOfDiaByTwo! * 1.5)),
      Offset(startingX! + oneThirdOfDia!,
          startingY! + radius! + (oneThirdOfDiaByTwo)!),
      Offset(
          endingX! - radius!, startingY! + radius! + (oneThirdOfDiaByTwo)!),
      Offset(
          endingX! - radius!, startingY! + radius! + (oneThirdOfDiaByTwo)!),
      Offset(endingX! - oneThirdOfDia!,
          startingY! + radius! + (oneThirdOfDiaByTwo)!),
      Offset(
          endingX! - (radius! / 2), endingY! - (oneThirdOfDiaByTwo! * 1.5)),
      Color(0xFFfe0944),
      Color(0xFFfeae96),
      Color(0xFFfe5c6e),
      'BAD');

  ughReview = ReviewState(
      Offset(leftSmileX, endingY! - (radius! / 2)),
      Offset(diameter!, endingY! - oneThirdOfDia!),
      Offset(endingX! - radius!, endingY! - oneThirdOfDia!),
      Offset(endingX! - radius!, endingY! - oneThirdOfDia!), //New
      Offset(endingX! - (radius! / 2), endingY! - oneThirdOfDia!),
      Offset(endingX! - (radius! / 2), endingY! - oneThirdOfDia!),
      Color(0xFFF9D976),
      Color(0xfff39f86),
      Color(0xFFf6bc7e),
      'UGH');

  okReview = ReviewState(
      Offset(leftSmileX, endingY! - (oneThirdOfDiaByTwo! * 1.5)),
      Offset(diameter!, endingY! - (oneThirdOfDiaByTwo! * 1.5)),
      Offset(endingX! - radius!, endingY! - (oneThirdOfDiaByTwo! * 1.5)),
      Offset(endingX! - radius!, endingY! - (oneThirdOfDiaByTwo! * 1.5)),
      Offset(startingX! + radius!, endingY! - (oneThirdOfDiaByTwo! * 1.5)),
      Offset(
          endingX! - (radius! / 2), endingY! - (oneThirdOfDiaByTwo! * 1.5)),
      Color(0xFF21e1fa),
      Color(0xff3bb8fd),
      Color(0xFF28cdfc),
      'OK');
  betterReview = ReviewState(
      Offset(leftSmileX, endingY! - (oneThirdOfDiaByTwo! * 1.75)),
      Offset(diameter!, endingY! - (oneThirdOfDiaByTwo! * 1.75)),
      Offset(endingX! - radius!, endingY! - (oneThirdOfDiaByTwo! * 1.75)),
      Offset(endingX! - radius!, endingY! - (oneThirdOfDiaByTwo! * 1.75)),
      Offset(startingX! + radius!, endingY! - (oneThirdOfDiaByTwo! * 1.75)),
      Offset(endingX! - (radius! / 2),
          endingY! - (oneThirdOfDiaByTwo! * 1.75)),
      Color(0xFF21e1fa),
      Color(0xff3bb8fd),
      Color(0xFF28cdfc),
      'Better');
  goodReview = ReviewState(
      Offset(
          startingX! + (radius! / 2), endingY! - (oneThirdOfDiaByTwo! * 2)),
      Offset(startingX! + oneThirdOfDia!,
          startingY! + (diameter! - oneThirdOfDiaByTwo!)),
      Offset(endingX! - radius!,
          startingY! + (diameter! - oneThirdOfDiaByTwo!)),
      Offset(endingX! - radius!,
          startingY! + (diameter! - oneThirdOfDiaByTwo!)),
      Offset(endingX! - oneThirdOfDia!,
          startingY! + (diameter! - oneThirdOfDiaByTwo!)),
      Offset(
          endingX! - (radius! / 2), endingY! - (oneThirdOfDiaByTwo! * 2)),
      Color(0xFF3ee98a),
      Color(0xFF41f7c7),
      Color(0xFF41f7c6),
      'GOOD');

  //get max width of text, that is width of GOOD text
  TextSpan spanGood = new TextSpan(
      style: new TextStyle(
          fontWeight: FontWeight.bold,
          fontSize: 52.0,
          color: okReview!.titleColor),
      text: "GOOD");
  TextPainter tpGood =
      new TextPainter(text: spanGood, textDirection: TextDirection.ltr);
  tpGood.layout();
  double goodWidth = tpGood.width;
  double halfGoodWidth = goodWidth / 2;

  //center points of BIG labels
  centerCenter = halfWidth;
  leftCenter = centerCenter! - goodWidth;
  rightCenter = centerCenter! + goodWidth;
}

if (slideValue <= 100) {
  tweenText(badReview!, ughReview!, slideValue / 100, canvas);
} else if (slideValue <= 200) {
  tweenText(ughReview!, okReview!, (slideValue - 100) / 100, canvas);
} else if (slideValue <= 300) {
  tweenText(okReview!, betterReview!, (slideValue - 200) / 100, canvas);
} else if (slideValue <= 400) {
  tweenText(betterReview!, goodReview!, (slideValue - 300) / 100, canvas);
} else if (slideValue <= 500) {
  tweenText(goodReview!, badReview!, (slideValue - 400) / 100, canvas);
}

//draw the outer circle------------------------------------------

final centerPoint = Offset(halfWidth!, halfHeight!);
final circlePaint = genGradientPaint(
  new Rect.fromCircle(
    center: centerPoint,
    radius: radius!,
  ),
  currentState!.startColor,
  currentState!.endColor,
  PaintingStyle.stroke,
)..strokeCap = StrokeCap.round;

canvas.drawCircle(centerPoint, radius!, circlePaint);
//---------------------------------------------------------------

//draw smile curve with path ------------------------------------------
canvas.drawPath(getSmilePath(currentState!), circlePaint);

//---------------------------------------------------------------

//draw eyes---------------------------------------------------
//ele calc
final leftEyeX = startingX! + oneThirdOfDia!;
final eyeY = startingY! + (oneThirdOfDia! + oneThirdOfDiaByTwo! / 4);
final rightEyeX = startingX! + (oneThirdOfDia! * 2);

final leftEyePoint = Offset(leftEyeX, eyeY);
final rightEyePoint = Offset(rightEyeX, eyeY);

final Paint leftEyePaintFill = genGradientPaint(
  new Rect.fromCircle(center: leftEyePoint, radius: eyeRadius!),
  currentState!.startColor,
  currentState!.endColor,
  PaintingStyle.fill,
);

final Paint rightEyePaintFill = genGradientPaint(
  new Rect.fromCircle(center: rightEyePoint, radius: eyeRadius!),
  currentState!.startColor,
  currentState!.endColor,
  PaintingStyle.fill,
);

canvas.drawCircle(leftEyePoint, eyeRadius!, leftEyePaintFill);
canvas.drawCircle(rightEyePoint, eyeRadius!, rightEyePaintFill);

//draw the edges of BAD Review
if (slideValue <= 100 || slideValue > 300) {
  double diff = -1.0;
  double tween = -1.0;

  if (slideValue <= 100) {
    diff = slideValue / 100;
    tween = lerpDouble(
        eyeY - (eyeRadiusbythree! * 0.6), eyeY - eyeRadius!, diff)!;
  } else if (slideValue > 300) {
    diff = (slideValue - 300) / 100;
    tween = lerpDouble(
        eyeY - eyeRadius!, eyeY - (eyeRadiusbythree! * 0.6), diff)!;
  }

  List<Offset> polygonPath = List<Offset>.empty(growable: true);
  polygonPath.add(Offset(leftEyeX - eyeRadiusbytwo!, eyeY - eyeRadius!));
  polygonPath.add(Offset(leftEyeX + eyeRadius!, tween));
  polygonPath.add(Offset(leftEyeX + eyeRadius!, eyeY - eyeRadius!));

  Path clipPath = new Path();
  clipPath.addPolygon(polygonPath, true);

  canvas.drawPath(clipPath, whitePaint);

  List<Offset> polygonPath2 = List<Offset>.empty(growable: true);
  polygonPath2.add(Offset(rightEyeX + eyeRadiusbytwo!, eyeY - eyeRadius!));
  polygonPath2.add(Offset(rightEyeX - eyeRadius!, tween));
  polygonPath2.add(Offset(rightEyeX - eyeRadius!, eyeY - eyeRadius!));

  Path clipPath2 = new Path();
  clipPath2.addPolygon(polygonPath2, true);

  canvas.drawPath(clipPath2, whitePaint);
}

//draw the balls of UGH Review
if (slideValue > 0 && slideValue < 200) {
  double diff = -1.0;
  double leftTweenX = -1.0;
  double leftTweenY = -1.0;

  double rightTweenX = -1.0;
  double rightTweenY = -1.0;

  if (slideValue <= 100) {

// bad to ugh
diff = slideValue / 100;
leftTweenX = lerpDouble(leftEyeX - eyeRadius!, leftEyeX, diff)!;
leftTweenY = lerpDouble(eyeY - eyeRadius!, eyeY, diff)!;

    rightTweenX = lerpDouble(rightEyeX + eyeRadius!, rightEyeX, diff)!;
    rightTweenY =
        lerpDouble(eyeY, eyeY - (eyeRadius! + eyeRadiusbythree!), diff)!;
  } else {

// ugh to ok
diff = (slideValue - 100) / 100;

    leftTweenX = lerpDouble(leftEyeX, leftEyeX - eyeRadius!, diff)!;
    leftTweenY = lerpDouble(eyeY, eyeY - eyeRadius!, diff)!;

    rightTweenX = lerpDouble(rightEyeX, rightEyeX + eyeRadius!, diff)!;
    rightTweenY =
        lerpDouble(eyeY - (eyeRadius! + eyeRadiusbythree!), eyeY, diff)!;
  }

  canvas.drawOval(
      Rect.fromLTRB(leftEyeX - (eyeRadius! + eyeRadiusbythree!),
          eyeY - (eyeRadius! + eyeRadiusbythree!), leftTweenX, leftTweenY),
      whitePaint);

  canvas.drawOval(
      Rect.fromLTRB(
          rightTweenX,
          eyeY,
          rightEyeX + (eyeRadius! + eyeRadiusbythree!),
          eyeY - (eyeRadius! + eyeRadiusbythree!)),
      whitePaint);
}

//---------------------------------------------------------------

//drawing stuff for debugging-----------------------------------

// canvas.drawRect(
// Rect.fromLTRB(0.0, 0.0, size.width, smileHeight), debugPaint);
// canvas.drawRect(
// Rect.fromLTRB(startingX, startingY, endingX, endingY), debugPaint);
//
// canvas.drawLine(
// Offset(startingX, startingY), Offset(endingX, endingY), debugPaint);
// canvas.drawLine(
// Offset(endingX, startingY), Offset(startingX, endingY), debugPaint);
// canvas.drawLine(Offset(startingX + radius, startingY),
// Offset(startingX + radius, endingY), debugPaint);
// canvas.drawLine(Offset(startingX, startingY + radius),
// Offset(endingX, startingY + radius), debugPaint);
//
// //horizontal lines
// canvas.drawLine(Offset(startingX, startingY + oneThirdOfDia),
// Offset(endingX, startingY + oneThirdOfDia), debugPaint);
// canvas.drawLine(Offset(startingX, endingY - oneThirdOfDia),
// Offset(endingX, endingY - oneThirdOfDia), debugPaint);
// canvas.drawLine(Offset(startingX, endingY - oneThirdOfDiaByTwo),
// Offset(endingX, endingY - oneThirdOfDiaByTwo), debugPaint);
//
// //vertical lines
// canvas.drawLine(Offset(startingX + oneThirdOfDiaByTwo, startingY),
// Offset(startingX + oneThirdOfDiaByTwo, endingY), debugPaint);
// canvas.drawLine(Offset(startingX + oneThirdOfDia, startingY),
// Offset(startingX + oneThirdOfDia, endingY), debugPaint);
// canvas.drawLine(Offset(endingX - oneThirdOfDia, startingY),
// Offset(endingX - oneThirdOfDia, endingY), debugPaint);
// canvas.drawLine(Offset(endingX - oneThirdOfDiaByTwo, startingY),
// Offset(endingX - oneThirdOfDiaByTwo, endingY), debugPaint);
//--------------------------------------------------------------
}

tweenText(ReviewState centerReview, ReviewState rightReview, double diff,
Canvas canvas) {
currentState = ReviewState.lerp(centerReview, rightReview, diff);

TextSpan spanCenter = new TextSpan(
    style: new TextStyle(
        fontWeight: FontWeight.bold,
        fontSize: 52.0,
        color:
            centerReview.titleColor.withAlpha(255 - (255 * diff).round())),
    text: centerReview.title);
TextPainter tpCenter =
    new TextPainter(text: spanCenter, textDirection: TextDirection.ltr);

TextSpan spanRight = new TextSpan(
    style: new TextStyle(
        fontWeight: FontWeight.bold,
        fontSize: 52.0,
        color: rightReview.titleColor.withAlpha((255 * diff).round())),
    text: rightReview.title);
TextPainter tpRight =
    new TextPainter(text: spanRight, textDirection: TextDirection.ltr);

tpCenter.layout();
tpRight.layout();

Offset centerOffset =
    new Offset(centerCenter! - (tpCenter.width / 2), smileHeight!);
Offset centerToLeftOffset =
    new Offset(leftCenter! - (tpCenter.width / 2), smileHeight!);

Offset rightOffset =
    new Offset(rightCenter! - (tpRight.width / 2), smileHeight!);
Offset rightToCenterOffset =
    new Offset(centerCenter! - (tpRight.width / 2), smileHeight!);

tpCenter.paint(
    canvas, Offset.lerp(centerOffset, centerToLeftOffset, diff)!);
tpRight.paint(canvas, Offset.lerp(rightOffset, rightToCenterOffset, diff)!);

}

Path getSmilePath(ReviewState state) {
var smilePath = Path();
smilePath.moveTo(state.leftOffset.dx, state.leftOffset.dy);
smilePath.quadraticBezierTo(state.leftHandle.dx, state.leftHandle.dy,
state.centerOffset.dx, state.centerOffset.dy);
smilePath.quadraticBezierTo(state.rightHandle.dx, state.rightHandle.dy,
state.rightOffset.dx, state.rightOffset.dy);
return smilePath;
}

Paint genGradientPaint(
Rect rect, Color startColor, Color endColor, PaintingStyle style) {
final Gradient gradient = new LinearGradient(
colors: [
startColor,
endColor,
],
);

return new Paint()
  ..strokeWidth = 10.0
  ..style = style
  ..shader = gradient.createShader(rect);

}

@OverRide
bool shouldRepaint(CustomPainter oldDelegate) {
return true;
}
}

class ReviewState {
//smile points
Offset leftOffset;
Offset centerOffset;
Offset centerset;

Offset rightOffset;
Offset leftHandle;
Offset rightHandle;

String title;
Color titleColor;

Color startColor;
Color endColor;

ReviewState(
this.leftOffset,
this.leftHandle,
this.centerOffset,
this.centerset,
this.rightHandle,
this.rightOffset,
this.startColor,
this.endColor,
this.titleColor,
this.title);

//create new state between given two states.
static ReviewState lerp(ReviewState start, ReviewState end, double ratio) {
var startColor = Color.lerp(start.startColor, end.startColor, ratio);
var endColor = Color.lerp(start.endColor, end.endColor, ratio);

return ReviewState(
    Offset.lerp(start.leftOffset, end.leftOffset, ratio)!,
    Offset.lerp(start.leftHandle, end.leftHandle, ratio)!,
    Offset.lerp(start.centerOffset, end.centerOffset, ratio)!,
    Offset.lerp(start.centerset, end.centerset, ratio)!,
    Offset.lerp(start.rightHandle, end.rightHandle, ratio)!,
    Offset.lerp(start.rightOffset, end.rightOffset, ratio)!,
    startColor!,
    endColor!,
    start.titleColor,
    start.title);

}
}
`

Assestment.dart
`import 'package:flutter/material.dart';
import 'package:relaxa/components/ArcChooser.dart';
import 'package:relaxa/components/smiley.dart';

class MyAssestmenetPage extends StatefulWidget {
final List question;
final int index;
MyAssestmenetPage({Key? key, required this.question, required this.index})
: super(key: key);

@OverRide
_MyAssestmenetPageState createState() => new _MyAssestmenetPageState();
}

class _MyAssestmenetPageState extends State
with TickerProviderStateMixin {
final PageController pageControl = new PageController(
initialPage: 2,
keepPage: false,
viewportFraction: 0.2,
);

int slideValue = 200;
int lastAnimPosition = 2;

AnimationController? animation;

List arcItems = List.empty(growable: true);

late ArcItem badArcItem;
late ArcItem ughArcItem;
late ArcItem okArcItem;
late ArcItem betterArcItem;

late ArcItem goodArcItem;

late Color startColor;
late Color endColor;
bool lastIndex = false;
@OverRide
void initState() {
super.initState();
print(widget.index);
print(widget.question.length);
if (widget.question.length == widget.index + 1) {
setState(() {
lastIndex = true;
});
}
print(lastIndex);
badArcItem =
ArcItem("Most Days", [Color(0xFFfe0944), Color(0xFFfeae96)], 0.0);
ughArcItem =
ArcItem("Sometimes", [Color(0xFFF9D976), Color(0xfff39f86)], 0.0);
okArcItem =
ArcItem("Not Sure", [Color(0xFF21e1fa), Color(0xff3bb8fd)], 0.0);
betterArcItem =
ArcItem("Not Exactly", [Color(0xFF21e1fa), Color(0xff3bb8fd)], 0.0);
goodArcItem = ArcItem("Never", [Color(0xFF3ee98a), Color(0xFF41f7c7)], 0.0);

arcItems.add(badArcItem);
arcItems.add(ughArcItem);
arcItems.add(okArcItem);
arcItems.add(betterArcItem);

arcItems.add(goodArcItem);

startColor = Color(0xFF21e1fa);
endColor = Color(0xff3bb8fd);

animation = new AnimationController(
  value: 0.0,
  lowerBound: 0.0,
  upperBound: 500.0,
  duration: const Duration(milliseconds: 800),
  vsync: this,
)..addListener(() {
    setState(() {
      slideValue = animation!.value.toInt();

      double ratio;

      if (slideValue <= 100) {
        ratio = animation!.value / 100;
        startColor =
            Color.lerp(badArcItem.colors[0], ughArcItem.colors[0], ratio)!;
        endColor =
            Color.lerp(badArcItem.colors[1], ughArcItem.colors[1], ratio)!;
      } else if (slideValue <= 200) {
        ratio = (animation!.value - 100) / 100;
        startColor =
            Color.lerp(ughArcItem.colors[0], okArcItem.colors[0], ratio)!;
        endColor =
            Color.lerp(ughArcItem.colors[1], okArcItem.colors[1], ratio)!;
      } else if (slideValue <= 300) {
        ratio = (animation!.value - 200) / 100;
        startColor = Color.lerp(
            okArcItem.colors[0], betterArcItem.colors[0], ratio)!;
        endColor = Color.lerp(
            okArcItem.colors[1], betterArcItem.colors[1], ratio)!;
      } else if (slideValue <= 400) {
        ratio = (animation!.value - 300) / 100;
        startColor = Color.lerp(
            betterArcItem.colors[0], goodArcItem.colors[0], ratio)!;
        endColor = Color.lerp(
            betterArcItem.colors[1], goodArcItem.colors[1], ratio)!;
      } else if (slideValue <= 500) {
        ratio = (animation!.value - 300) / 100;
        startColor =
            Color.lerp(goodArcItem.colors[0], badArcItem.colors[0], ratio)!;
        endColor =
            Color.lerp(goodArcItem.colors[1], badArcItem.colors[1], ratio)!;
      }
    });
  });

animation!.animateTo(slideValue.toDouble());

}

@OverRide
Widget build(BuildContext context) {
var textStyle = new TextStyle(
color: Colors.white, fontSize: 24.00, fontWeight: FontWeight.bold);

return Container(
  color: Colors.white,
  margin: MediaQuery.of(context).padding,
  child: SingleChildScrollView(
    child: Column(
      mainAxisAlignment: MainAxisAlignment.spaceBetween,
      children: <Widget>[
        Center(
          child: Padding(
            padding: const EdgeInsets.all(26.0),
            child: Text(
              widget.question[widget.index],
              textAlign: TextAlign.center,
              style: Theme.of(context).textTheme.headline5,
            ),
          ),
        ),
        SizedBox(
          height: 60,
        ),
        CustomPaint(
          size: Size(MediaQuery.of(context).size.width,
              (MediaQuery.of(context).size.width / 2) + 60),
          painter: SmilePainter(slideValue),
        ),

// Slider(
// min: 0.0,
// max: 400.0,
// value: slideValue.toDouble(),
// onChanged: (double newValue) {
// setState(() {
// slideValue = newValue.round();
// });
// },
// ),

// new SizedBox(
// height: 50.0,
// child: new NotificationListener(
// onNotification: (ScrollNotification notification){
// if(!notification.metrics.atEdge){
// print('_MyReviewPageState.build ' + MediaQuery.of(context).size.width.toString() + " " + notification.metrics.pixels.toString());
// }
//
// },
// child: PageView.builder(
// pageSnapping: true,
// onPageChanged: (int value) {
// print('_MyReviewPageState._onPageChanged ' + value.toString());
// animation.animateTo(value*100.0);
// },
// controller: pageControl,
// itemCount: arcItems.length,
// physics: new AlwaysScrollableScrollPhysics(),
// itemBuilder: (context, index) {
// return new Container(
// decoration: new BoxDecoration(
// gradient: new LinearGradient(
// colors: [
// arcItems[index].colors[0],
// arcItems[index].colors[1]
// ]
// ),
// ),
// alignment: Alignment.center,
// child: new Text(
// arcItems[index].text,
// style: textStyle,
// ));
// },
// ),
// ),
// ),
Stack(
alignment: AlignmentDirectional.bottomCenter,
children: [
ArcChooser()
..arcSelectedCallback = (int pos, ArcItem item) {
int animPosition = pos - 2;
if (animPosition > 4) {
animPosition = animPosition - 5;
}

                  if (animPosition < 0) {
                    animPosition = 5 + animPosition;
                  }

                  if (lastAnimPosition == 4 && animPosition == 0) {
                    animation!.animateTo(5 * 100.0);
                  } else if (lastAnimPosition == 0 && animPosition == 4) {
                    animation!.forward(from: 5 * 100.0);
                    animation!.animateTo(animPosition * 100.0);
                  } else if (lastAnimPosition == 0 && animPosition == 3) {
                    animation!.forward(from: 5 * 100.0);
                    animation!.animateTo(animPosition * 100.0);
                  } else if (lastAnimPosition == 0 && animPosition == 1) {
                    animation!.forward(from: 0.0);
                    animation!.animateTo(animPosition * 100.0);
                  } else {
                    animation!.animateTo(animPosition * 100.0);
                  }

                  lastAnimPosition = animPosition;
                },
              Padding(
                padding: const EdgeInsets.all(28.0),
                child: lastIndex
                    ? MaterialButton(
                        onPressed: () => {},
                        shape: RoundedRectangleBorder(
                            borderRadius: BorderRadius.circular(25.0)),
                        elevation: 8.0,
                        child: Container(
                            width: 150.0,
                            height: 50.0,
                            decoration: BoxDecoration(
                              gradient: LinearGradient(
                                  colors: [startColor, endColor]),
                            ),
                            alignment: Alignment.center,
                            child: Text(
                              'SUBMIT',
                              style: textStyle,
                            )),
                      )
                    : MaterialButton(
                        onPressed: () => Navigator.of(context).push(
                          MaterialPageRoute(
                              builder: (_) => MyAssestmenetPage(
                                    question: widget.question,
                                    index: widget.index + 1,
                                  )),
                        ),
                        shape: RoundedRectangleBorder(
                            borderRadius: BorderRadius.circular(25.0)),
                        elevation: 8.0,
                        child: Container(
                            width: 150.0,
                            height: 50.0,
                            decoration: BoxDecoration(
                              gradient: LinearGradient(
                                  colors: [startColor, endColor]),
                            ),
                            alignment: Alignment.center,
                            child: Text(
                              'Next',
                              style: textStyle,
                            )),
                      ),

// child: RaisedButton(
// shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16.0)),
// child: Text('SUBMIT'),
// onPressed: () {
// print('cool');
// },
// ),
)
]),
],
),
),
);
}
}
`

Note that this code is in Null Safety.
image
image
Initially the Ugh is not visible within first round in the list. Help

@jaydeepkaria-mi jaydeepkaria-mi added the enhancement New feature or request label Dec 19, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants