Created
November 6, 2020 09:09
-
-
Save JohnKim/a0fc1d41829226883c39c76995303f22 to your computer and use it in GitHub Desktop.
Face Example (Flutter)
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'; | |
double degreesToRads(double deg) { | |
return (deg * pi) / 180.0; | |
} | |
void main() { | |
runApp(Face()); | |
} | |
class Face extends StatelessWidget { | |
@override | |
Widget build(BuildContext context) { | |
return Container( | |
child: CustomPaint( | |
painter: _MyPainter(1.2, color: Colors.white), | |
), | |
); | |
} | |
} | |
class _MyPainter extends CustomPainter { | |
_MyPainter( | |
animationValue, { | |
this.color = const Color(0xFF615f56), | |
}) : activeIndex = animationValue.floor(), | |
unitAnimatingValue = (animationValue * 10 % 10 / 10); | |
final int activeIndex; | |
Color color; | |
final double unitAnimatingValue; | |
@override | |
void paint(Canvas canvas, Size size) { | |
_drawEye(canvas, size); | |
_drawMouth(canvas, size); | |
} | |
@override | |
bool shouldRepaint(_MyPainter oldDelegate) { | |
return unitAnimatingValue != oldDelegate.unitAnimatingValue || | |
activeIndex != oldDelegate.activeIndex; | |
} | |
_drawEye(canvas, size) { | |
var angle = 0.0; | |
var wide = 0.0; | |
switch (activeIndex) { | |
case 0: // 0 -> 0.99 angle 조정 | |
angle = 55 - unitAnimatingValue * 50; | |
wide = 80.0; | |
break; | |
case 1: // 1 -> 1.99 width 조정 | |
wide = 80 - unitAnimatingValue * 80; | |
angle = 5; | |
break; | |
} | |
var degree1 = 90 * 3 + angle; | |
var degree2 = 90 * 3 - angle + wide; | |
var x1 = size.width / 2 * 0.65; | |
var x2 = size.width - x1; | |
var y = size.height * 0.41; | |
var eyeRadius = size.width * (5 / 60); // 60 diameter -> 5.0; | |
var paint = Paint()..color = color; | |
canvas.drawArc( | |
Rect.fromCircle( | |
center: Offset(x1, y), | |
radius: eyeRadius, | |
), | |
degreesToRads(degree1), // 270d + angle | |
degreesToRads(360 - wide), | |
false, | |
paint, | |
); | |
canvas.drawArc( | |
Rect.fromCircle( | |
center: Offset(x2, y), | |
radius: eyeRadius, | |
), | |
degreesToRads(degree2), | |
degreesToRads(360 - wide), | |
false, | |
paint, | |
); | |
} | |
_drawMouth(Canvas canvas, size) { | |
var upperY = size.height * 0.70; | |
var lowerY = size.height * 0.77; | |
var middleY = (lowerY - upperY) / 2 + upperY; | |
var leftX = size.width / 2 * 0.65; | |
var rightX = size.width - leftX; | |
var middleX = size.width / 2; | |
double y1, y3, x2, y2; | |
Path path2; | |
switch (activeIndex) { | |
case 0: | |
y1 = lowerY; | |
x2 = middleX; | |
y2 = upperY; | |
y3 = lowerY; | |
break; | |
case 1: | |
y1 = lowerY; | |
x2 = middleX; | |
y2 = unitAnimatingValue * (middleY - upperY) + upperY; | |
y3 = lowerY - unitAnimatingValue * (lowerY - upperY); | |
break; | |
case 2: | |
y1 = unitAnimatingValue * (upperY - lowerY) + lowerY; | |
x2 = middleX; | |
y2 = unitAnimatingValue * (lowerY + 3 - middleY) + middleY; | |
y3 = upperY; | |
break; | |
case 3: | |
y1 = upperY; | |
x2 = middleX; | |
y2 = lowerY + 3; | |
y3 = upperY; | |
path2 = Path() | |
..moveTo(leftX, y1) | |
..quadraticBezierTo( | |
x2, | |
y2, | |
upperY - 2.5, | |
y3 - 2.5, | |
) | |
..quadraticBezierTo( | |
x2, | |
y2 - unitAnimatingValue * (y2 - upperY + 2.5), | |
leftX, | |
upperY - 2.5, | |
) | |
..close(); | |
break; | |
case 4: | |
y1 = upperY; | |
x2 = middleX; | |
y2 = lowerY + 3; | |
y3 = upperY; | |
path2 = Path() | |
..moveTo(leftX, y1) | |
..quadraticBezierTo( | |
x2, | |
y2, | |
upperY - 2.5, | |
y3 - 2.5, | |
) | |
..quadraticBezierTo( | |
x2, | |
upperY - 2.5, | |
leftX, | |
upperY - 2.5, | |
) | |
..close(); | |
break; | |
} | |
var path = Path() | |
..moveTo(leftX, y1) | |
..quadraticBezierTo( | |
x2, | |
y2, | |
rightX, | |
y3, | |
); | |
canvas.drawPath( | |
path, | |
Paint() | |
..color = color | |
..style = PaintingStyle.stroke | |
..strokeCap = StrokeCap.round | |
..strokeWidth = size.width * (5 / 60)); | |
if (path2 != null) { | |
canvas.drawPath( | |
path2, | |
Paint() | |
..color = color | |
..style = PaintingStyle.fill | |
..strokeCap = StrokeCap.round, | |
); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
https://dartpad.dev/a0fc1d41829226883c39c76995303f22