大家好,我刚刚开始学习颤动动画并使用颤动曲线,来自颤动曲线网站 使用补间值,就像
_animation = Tween<double>(begin: -100, end: 0).animate(
CurvedAnimation(
parent: _controller,
curve: Curves.bounceInOut,
),
);)
我想使用动画构建器将其与带有定位小部件的圆形容器一起在堆栈中进行动画处理 代码就像这样
Stack(
children: [
// background image view
Container(
decoration: const BoxDecoration(
image: DecorationImage(
image: AssetImage('images/sky.webp'), fit: BoxFit.cover),
),
),
//! I want to animate this like a bouncing ball
AnimatedBuilder(
animation: _controller,
builder: (context, child) {
return Positioned(
// This is the animation value as position of the circular container
bottom: _animation.value,
left: _animation.value + 50,
child: Container(
height: 250,
width: 250,
decoration: const BoxDecoration(
shape: BoxShape.circle,
// borderRadius: BorderRadius.only(
// topLeft: Radius.circular(15),
// topRight: Radius.circular(15),
// ),
image: DecorationImage(
image: AssetImage(
'images/colz.jpg',
),
fit: BoxFit.cover,
),
),
),
);
},
)
],
),
我想要弹跳方向为
从这里开始反弹曲线
--^
^---- > 曲线到此结束
这就是代码之后发生的事情
我认为使用两个不同的动画共享相同的控制器来驱动它们可能会更好。调整水平方向的控制器可以是与调整水平方向的控制器不同的曲线。
我已经修改了您的原始代码来执行此操作,并添加了一个示例,说明您如何制作自己的曲线,从而为您提供所需的弹性。请注意,我在底部的演示曲线非常粗糙,如果不与线性主曲线配对,可能会很卡顿。您可以通过平均每条曲线的起点和终点来使它们更平滑 - 我将把它留给您修改。
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return const MaterialApp(
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key});
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage>
with SingleTickerProviderStateMixin {
late AnimationController _controller;
late Animation<double> _horizontalAnimation;
late Animation<double> _verticalAnimation;
@override
void initState() {
_controller = AnimationController(
vsync: this,
duration: const Duration(
seconds: 5,
),
);
_horizontalAnimation = Tween<double>(begin: -1.0, end: 1.0).animate(
CurvedAnimation(
parent: _controller,
// curve: Curves.bounceInOut,
// TODO: Try to experiment with this a bit too!
curve: const InterpolateCurve(
primary: Curves.linear,
secondary: Curves.bounceInOut,
),
),
);
_verticalAnimation = Tween<double>(begin: -1.0, end: 1.0).animate(
CurvedAnimation(
parent: _controller,
curve: Curves.linear,
// TODO: You may even be able to experiment with this a bit
// curve: const InterpolateCurve(
// primary: Curves.linear,
// secondary: WhipCurve(Curves.easeInOut),
// startTransition: 0.2,
// endTransition: 0.8,
// ),
),
);
super.initState();
_controller.forward();
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Drag and Drop Example'),
),
body: Stack(
children: [
// background image view
Container(
decoration: const BoxDecoration(
image: DecorationImage(
image: NetworkImage(
'https://hdwallpaperim.com/wp-content/uploads/2017/08/25/462707-universe-galaxy-space-stars.jpg'),
fit: BoxFit.cover),
),
),
//! I want to animate this like a bouncing ball
AnimatedBuilder(
animation: _controller,
builder: (context, child) {
return Align(
alignment: Alignment(
_horizontalAnimation.value, _verticalAnimation.value),
// This is the animation value as position of the circular container
child: Container(
height: 250,
width: 250,
decoration: BoxDecoration(
shape: BoxShape.circle,
// borderRadius: BorderRadius.only(
// topLeft: Radius.circular(15),
// topRight: Radius.circular(15),
// ),
// image: DecorationImage(
// image: AssetImage(
// 'images/colz.jpg',
// ),
// fit: BoxFit.cover,
// ),
color: Colors.indigo.shade900,
),
),
);
},
)
],
),
);
}
}
// Try this too:
class InterpolateCurve extends Curve {
final Curve primary;
final Curve secondary;
final double startTransition;
final double endTransition;
const InterpolateCurve({
required this.primary,
required this.secondary,
this.startTransition = 0.4,
this.endTransition = 0.6,
});
@override
double transform(double t) {
t = t.clamp(0.0, 1.0);
// We want to squiggle in the middle a bit so...
if (t <= startTransition || t >= endTransition) {
return primary.transform(t);
}
final double centerPeriod = endTransition - startTransition;
final double centerSegementScalar = 1.0 / centerPeriod;
t = (t - startTransition) * centerSegementScalar;
t = t.clamp(0.0, 1.0);
t = secondary.transform(t);
t = (t / centerSegementScalar) + startTransition;
return t;
}
}
class WhipCurve extends Curve {
final Curve curve;
const WhipCurve(
this.curve,
);
@override
double transform(double t) {
t = t.clamp(0.0, 1.0);
if (t <= 1 / 3) {
return curve.transform(t * 3);
}
if (t >= 2 / 3) {
t = t - (2 / 3);
return curve.transform(t * 3);
} else {
t = (t - (1 / 3));
return 1.0 - curve.transform(t * 3);
}
}
}
另请注意,我将您的“定位”小部件替换为“对齐”小部件;我认为 Align 可能就是您想要的 - 定位以使其在屏幕上移动需要一些 MediaQuery.of(context).size 调用才能将其正确缩放到屏幕,而 Align 只会将其保留在屏幕上。
我显然没有你的图片,所以你需要将它们添加回来。