Skip to content

Instantly share code, notes, and snippets.

@Luckey-Elijah
Last active September 22, 2022 21:05
Show Gist options
  • Save Luckey-Elijah/7a48050ec5f8938508a281f644cc8d99 to your computer and use it in GitHub Desktop.
Save Luckey-Elijah/7a48050ec5f8938508a281f644cc8d99 to your computer and use it in GitHub Desktop.
import 'package:flutter/material.dart';
void main() => runApp(const MaterialApp(home: EyesThatFollow()));
class EyesThatFollow extends StatefulWidget {
const EyesThatFollow({super.key});
@override
State<EyesThatFollow> createState() => _EyesThatFollowState();
}
class _EyesThatFollowState extends State<EyesThatFollow> {
Offset? widgetPosition, cusorPosition;
final key = GlobalKey();
@override
void initState() {
super.initState();
WidgetsBinding.instance
.addPostFrameCallback((_) => _updateWidgetPosition());
}
void _updateWidgetPosition() =>
setState(() => widgetPosition = getWidgetOffset(key));
@override
Widget build(BuildContext context) {
final canUsePupil = widgetPosition != null && cusorPosition != null;
return MouseRegion(
onHover: (event) => setState(() => cusorPosition = event.position),
onExit: (event) => setState(() => cusorPosition = null),
onEnter: (_) => _updateWidgetPosition(),
child: Scaffold(
body: Center(
child: Stack(
alignment: AlignmentDirectional.center,
children: [
CustomPaint(
key: key,
size: const Size(80, 50),
painter: CirclePainter(fill: !canUsePupil),
),
if (canUsePupil) Pupil(radians(widgetPosition!, cusorPosition!))
],
),
),
),
);
}
}
class Pupil extends StatelessWidget {
const Pupil(this.direction, {super.key});
final double direction;
@override
Widget build(BuildContext context) {
return Transform.translate(
offset: Offset.fromDirection(direction).scale(24, 10),
child: CustomPaint(
size: const Size(20, 15),
painter: CirclePainter(fill: true, color: Colors.blue),
),
);
}
}
double radians(Offset element, Offset cursor) => (cursor - element).direction;
Offset? getWidgetOffset(GlobalKey key) {
final renderBox = key.currentContext?.findRenderObject() as RenderBox?;
final origin = renderBox?.localToGlobal(Offset.zero);
return renderBox?.size.center(origin!);
}
class CirclePainter extends CustomPainter {
CirclePainter({
bool fill = false,
Color color = Colors.grey,
}) : _paint = Paint()
..color = color
..strokeWidth = 2
..style = fill ? PaintingStyle.fill : PaintingStyle.stroke;
final Paint _paint;
@override
void paint(Canvas canvas, Size size) =>
canvas.drawOval(Rect.fromLTWH(0, 0, size.width, size.height), _paint);
@override
bool shouldRepaint(CustomPainter oldDelegate) => false;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment