Skip to content

Instantly share code, notes, and snippets.

@chooyan-eng
Created March 25, 2025 00:48
Show Gist options
  • Select an option

  • Save chooyan-eng/4e7258fae87c2d858b2a8b06163d343e to your computer and use it in GitHub Desktop.

Select an option

Save chooyan-eng/4e7258fae87c2d858b2a8b06163d343e to your computer and use it in GitHub Desktop.
import 'package:flutter/material.dart';
import 'package:flutter/physics.dart';
void main() {
runApp(const MaterialApp(home: AnimationPage()));
}
class AnimationPage extends StatefulWidget {
const AnimationPage({super.key});
@override
State<AnimationPage> createState() => _AnimationPageState();
}
class _AnimationPageState extends State<AnimationPage>
with TickerProviderStateMixin {
late final AnimationController _controllerX;
late final AnimationController _controllerY;
final _boxSize = 60.0;
double _valueX = 20;
double _valueY = 100;
@override
void initState() {
super.initState();
/// [AnimationController] for x axis
_controllerX = AnimationController.unbounded(vsync: this)..addListener(() {
setState(() {
_valueX = _controllerX.value;
});
});
/// [AnimationController] for y axis
_controllerY = AnimationController.unbounded(vsync: this)..addListener(() {
setState(() {
_valueY = _controllerY.value;
});
});
}
static const _description = SpringDescription(
mass: 0.8,
stiffness: 50,
damping: 10,
);
void _startAnimation(
Offset initialPosition,
Offset destination,
Offset velocity,
) {
// start animation for x axis
_controllerX.animateWith(
SpringSimulation(
_description,
initialPosition.dx,
destination.dx,
velocity.dx,
),
);
/// simulate y-axis with [GravitySimulation] with previous bouncing logic
_controllerY.animateWith(
SpringSimulation(
_description,
initialPosition.dy,
destination.dy,
velocity.dy,
),
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: GestureDetector(
onTapDown: (details) {
final destination = Offset(
details.globalPosition.dx - _boxSize / 2,
details.globalPosition.dy - _boxSize / 2,
);
_startAnimation(
Offset(_valueX, _valueY),
destination,
Offset(_controllerX.velocity, _controllerY.velocity),
);
},
child: Stack(
children: [
CustomPaint(size: Size.infinite, painter: _GridPainter()),
Positioned(
top: _valueY,
left: _valueX,
child: Container(
width: _boxSize,
height: _boxSize,
color: Colors.blue,
),
),
],
),
),
);
}
}
/// background grid
class _GridPainter extends CustomPainter {
@override
void paint(Canvas canvas, Size size) {
final paint =
Paint()
..color = Colors.grey.withOpacity(0.3)
..strokeWidth = 0.5;
for (var i = 0.0; i < size.width; i += 10) {
canvas.drawLine(Offset(i, 0), Offset(i, size.height), paint);
}
for (var i = 0.0; i < size.height; i += 10) {
canvas.drawLine(Offset(0, i), Offset(size.width, i), paint);
}
}
@override
bool shouldRepaint(covariant CustomPainter oldDelegate) => false;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment