Created
July 10, 2020 13:22
-
-
Save pskink/91a7579ee2915a3cbaf83c22ecd7afb7 to your computer and use it in GitHub Desktop.
This file contains hidden or 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
| class CustomImageScroller extends StatefulWidget { | |
| final String asset; | |
| CustomImageScroller({Key key, this.asset}) : super(key: key); | |
| @override | |
| _CustomImageScrollerState createState() => _CustomImageScrollerState(); | |
| } | |
| class _CustomImageScrollerState extends State<CustomImageScroller> with TickerProviderStateMixin { | |
| AnimationController xc; | |
| AnimationController yc; | |
| ValueNotifier<ui.Image> imageNotifier; | |
| double dx = 0.0; | |
| double dy = 0.0; | |
| @override | |
| void initState() { | |
| super.initState(); | |
| xc = AnimationController.unbounded(vsync: this); | |
| yc = AnimationController.unbounded(vsync: this); | |
| imageNotifier = ValueNotifier(null); | |
| Future(() => rootBundle.load(widget.asset).then(_decodeAssetData)); | |
| } | |
| @override | |
| Widget build(BuildContext context) { | |
| print('_CustomImageScrollerState.build'); | |
| return GestureDetector( | |
| onPanUpdate: (d) { | |
| _handlePanUpdate(xc, dx, d.delta.dx); | |
| _handlePanUpdate(yc, dy, d.delta.dy); | |
| }, | |
| onPanEnd: (d) { | |
| _handlePanEnd(xc, dx, d.velocity.pixelsPerSecond.dx); | |
| _handlePanEnd(yc, dy, d.velocity.pixelsPerSecond.dy); | |
| }, | |
| child: CustomPaint( | |
| painter: ImagePainter(xc, yc, imageNotifier), | |
| child: SizedBox.expand(), | |
| ), | |
| ); | |
| } | |
| void _decodeAssetData(data) async { | |
| print('_decodeAssetData'); | |
| var image = await decodeImageFromList(data.buffer.asUint8List()); | |
| imageNotifier.value = image; | |
| RenderBox rb = context.findRenderObject(); | |
| dx = rb.size.width - image.width; | |
| dy = rb.size.height - image.height; | |
| if (dx > 0) xc.value = dx / 2; | |
| if (dy > 0) yc.value = dy / 2; | |
| } | |
| void _handlePanUpdate(AnimationController controller, double sizeDifference, double delta) { | |
| if (sizeDifference < 0) { | |
| controller.value += delta; | |
| } | |
| } | |
| final sd = SpringDescription.withDampingRatio( | |
| mass: 0.5, | |
| stiffness: 300.0, | |
| ratio: 0.85, | |
| ); | |
| void _handlePanEnd(AnimationController controller, double sizeDifference, double velocity) { | |
| if (sizeDifference < 0) { | |
| var simulation = (sizeDifference <= controller.value && controller.value <= 0)? | |
| ClampedSimulation(FrictionSimulation(0.001, controller.value, velocity), xMin: sizeDifference, xMax: 0) : | |
| SpringSimulation(sd, controller.value, controller.value.clamp(sizeDifference, 0.0), 0); | |
| controller.animateWith(simulation); | |
| } | |
| } | |
| } | |
| class ImagePainter extends CustomPainter { | |
| final AnimationController xc, yc; | |
| final ValueNotifier<ui.Image> imageNotifier; | |
| ImagePainter(this.xc, this.yc, this.imageNotifier) : super(repaint: Listenable.merge([xc, yc, imageNotifier])); | |
| @override | |
| void paint(ui.Canvas canvas, ui.Size size) { | |
| // print('$xc $yc $imageNotifier'); | |
| canvas.clipRect(Offset.zero & size); | |
| if (imageNotifier.value != null) { | |
| canvas.drawImage(imageNotifier.value, Offset(xc.value, yc.value), Paint()); | |
| } | |
| } | |
| @override | |
| bool shouldRepaint(CustomPainter oldDelegate) => true; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment