Skip to content

Instantly share code, notes, and snippets.

@roipeker
Last active August 19, 2021 17:12
Show Gist options
  • Save roipeker/9dd0d83fd70874df4c211aafa487a256 to your computer and use it in GitHub Desktop.
Save roipeker/9dd0d83fd70874df4c211aafa487a256 to your computer and use it in GitHub Desktop.
Rect area tween.
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return const MaterialApp(
home: HomePage(),
);
}
}
class HomePage extends StatefulWidget {
const HomePage({Key? key}) : super(key: key);
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
Rect rect = Rect.zero;
// To take FlutterLogo() size and coordinates.
final flutterKey = GlobalKey();
@override
Widget build(BuildContext context) {
return RectAreaWidget(
rect: rect,
usePercent: false,
child: Scaffold(
appBar: AppBar(),
body: GestureDetector(
onTap: () {
final ro =
flutterKey.currentContext!.findRenderObject() as RenderBox;
final pos = ro.localToGlobal(Offset.zero);
setState(() {
rect = pos & ro.size;
});
},
child: Center(
child: Text.rich(
TextSpan(
text: 'Home page',
style: Theme.of(context).textTheme.headline1,
mouseCursor: SystemMouseCursors.click,
children: [
WidgetSpan(
child: FlutterLogo(
key: flutterKey,
size: 70,
),
alignment: PlaceholderAlignment.middle,
),
TextSpan(
text: ' click here',
style: Theme.of(context).textTheme.caption,
),
],
),
textAlign: TextAlign.center,
),
),
),
),
);
}
}
/// just a sample...
class RectAreaWidget extends StatefulWidget {
final Widget child;
final Rect rect;
final bool usePercent;
const RectAreaWidget({
Key? key,
required this.child,
required this.rect,
this.usePercent = false,
}) : super(key: key);
@override
_RectAreaWidgetState createState() => _RectAreaWidgetState();
}
class _RectAreaWidgetState extends State<RectAreaWidget>
with SingleTickerProviderStateMixin {
late final _controller = AnimationController(
vsync: this,
duration: const Duration(seconds: 2),
);
late List<Rect> _rects;
Animation? _seq;
late Rect screenSize;
@override
void didUpdateWidget(RectAreaWidget oldWidget) {
/// compare if the "rect" area changed...
// if (oldWidget.rect != widget.rect) {
WidgetsBinding.instance!.addPostFrameCallback((timeStamp) {
updateRects();
_controller.reset();
_controller.forward();
setState(() {});
});
// }
super.didUpdateWidget(oldWidget);
}
void updateRects() {
final r = widget.rect;
if (mounted) {
screenSize = Offset.zero & context.size!;
}
_rects = [
screenSize,
Rect.fromLTRB(0.0, 0.0, r.right, r.bottom),
Rect.fromLTWH(r.left, r.top, r.width, r.height),
];
_seq = TweenSequence([
TweenSequenceItem(
tween: RectTween(begin: _rects[0], end: _rects[1]),
weight: 2,
),
TweenSequenceItem(
tween: RectTween(begin: _rects[1], end: _rects[2]),
weight: 2,
),
]).animate(
CurvedAnimation(
parent: _controller,
curve: const Interval(0.3, 1.0, curve: Curves.easeInOut),
),
);
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
if (_seq == null) {
return widget.child;
}
final seq = _seq!;
return AnimatedBuilder(
animation: seq,
builder: (_, child) {
return CustomPaint(
foregroundPainter: RectAreaPaint(
rect: seq.value,
usePercent: widget.usePercent,
),
willChange: true,
child: child,
);
},
child: widget.child,
);
}
}
/// painter.
class RectAreaPaint extends CustomPainter {
final Rect rect;
final bool usePercent;
RectAreaPaint({
required this.rect,
this.usePercent = false,
});
@override
void paint(Canvas canvas, Size size) {
final screenPaint = Paint()..color = Colors.black38;
final borderPaint = Paint()
..color = const Color(0xffCCCCCC)
..style = PaintingStyle.stroke
..strokeWidth = 2;
final screenRect = Offset.zero & size;
var r = rect;
final _areaRect = usePercent
? Rect.fromLTWH(
r.left * size.width,
r.top * size.height,
r.width * size.width,
r.height * size.height,
)
: r;
final areaPath = Path()..addRect(_areaRect);
final maskPath = Path.combine(
PathOperation.difference,
Path()..addRect(screenRect),
areaPath,
);
canvas.drawPath(maskPath, screenPaint);
canvas.drawPath(areaPath, borderPaint);
}
@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