Files
flutter_wisetronic/lib/widgets/general/parabolic_animation_widget.dart
2021-08-31 13:28:33 -04:00

91 lines
3.0 KiB
Dart

import 'package:flutter/material.dart';
import 'package:flutter/physics.dart';
// ignore: must_be_immutable
class ParabolicAnimationWidget extends AnimatedWidget {
final GlobalKey stackKey;
final GlobalKey startKey;
final GlobalKey endKey;
final double size;
final Color color;
final Offset startAdjustOffset;
final Offset endAdjustOffset;
ParabolicAnimationWidget({
@required Animation<double> animation,
@required this.stackKey,
@required this.startKey,
@required this.endKey,
this.size = 20.0,
this.color = Colors.red,
this.startAdjustOffset = Offset.zero,
this.endAdjustOffset = Offset.zero,
}) : super(listenable: animation);
Offset _startOffset;
Offset _endOffset;
@override
Widget build(BuildContext context) {
_calPoints();
final Animation<double> animation = listenable;
final double time = animation.value;
// 设time=1 已知两点坐标 和 初速度 可求出 加速度 a
// double x(double time) => _x + _v * time + 0.5 * _a * time * time;
final double initV = -400; //纵坐标初速度, 负值为向上抛
final double acceleration =
(_endOffset.dy - _startOffset.dy - initV) / 0.5; //求纵坐标加速度
final GravitySimulation spy = GravitySimulation(
acceleration, _startOffset.dy, _endOffset.dy, initV); //y轴加速度运动 模拟
final GravitySimulation spx = GravitySimulation(0, _startOffset.dx,
_endOffset.dx, _endOffset.dx - _startOffset.dx); //x轴匀速模拟 加速度为0
final Animation<double> opacity = Tween<double>(begin: 1, end: 0).animate(
CurvedAnimation(
parent: animation, curve: Interval(0.9, 1, curve: Curves.ease)));
return Positioned(
top: spy.x(time),
left: spx.x(time),
child: Opacity(
opacity: opacity.value,
child: Container(
height: size,
width: size,
decoration: BoxDecoration(
color: color,
borderRadius: BorderRadius.all(Radius.circular(size / 2.0))),
),
),
);
}
void _calPoints() {
if (_startOffset == null) {
RenderBox stackBox = stackKey.currentContext.findRenderObject();
Offset stackBoxOffset = stackBox.globalToLocal(Offset.zero);
EdgeInsets startMargin = _margin(startKey);
RenderBox startBox = startKey.currentContext.findRenderObject();
_startOffset = startBox.localToGlobal(Offset(
startMargin.left + startAdjustOffset.dx,
stackBoxOffset.dy + startMargin.top + startAdjustOffset.dy));
EdgeInsets endMargin = _margin(endKey);
RenderBox endBox = endKey.currentContext.findRenderObject();
_endOffset = endBox.localToGlobal(Offset(
endMargin.left + endAdjustOffset.dx,
stackBoxOffset.dy + endMargin.top + endAdjustOffset.dy));
}
}
EdgeInsets _margin(GlobalKey key) {
final Widget widget = key.currentContext.widget;
EdgeInsets margin = (widget is Container) ? widget.margin : EdgeInsets.zero;
return margin ?? EdgeInsets.zero;
}
}