When an Animation controller is set forward(), I want the Animation attached to it to have a CurvedAnimation of Curves.elasticIn
When an Animation controller is set reverse(), I want the Animation attached to it to have a CurvedAnimation of Curves.elasticOut
I thought of changing the Curve just before the animation but it does not change it.
This is my attempt:
if (!pinDropAnimationController.isAnimating) {
if (mapController.isCameraMoving) {
pinDropAnimationTween.animate(
new CurvedAnimation(
parent: pinDropAnimationController, curve: Curves.linear));
pinDropAnimationController.forward();
} else {
pinDropAnimationTween.animate(
new CurvedAnimation(
parent: pinDropAnimationController, curve: Curves.elasticIn));
pinDropAnimationController.reverse();
}
}
}
On the CurvedAnimation constructor you have an argument named reverseCurve !
It does the job really well :)
Related
I am trying to make a colour transition animation inside a StreamBuilder which is inside a stateless widget. I have no idea how to perform that since all the examples and tutorials about this subject use a Stateful Widget.
I thought about using FadeTransition Widget but and maybe store the state in my Bloc that controls that view.
Please give me any suggestions if you have, Thank you.
To perform a fade in transition in a streambuilder, it's easy, simply use a widget called AnimatedSwitcher :
#override
Widget build(BuildContext context) {
return StreamBuilder(
stream: FirebaseAuth.instance.onAuthStateChanged,
builder: (BuildContext context, snapshot) {
return AnimatedSwitcher(
duration: Duration(seconds: 1),
child: _getMainWidget(snapshot, context),
);
},
);
}
Here we use an AnimatedSwitcher to animate a transition when the child of the AnimatedSwitcher change's, the default animation is a fade animation, but you could add your custom animation by passing the widget a TransitionBuilder as an argument
I am trying to add or remove an object from scene:
const rootObject = this.scene.getObjectByName('Object Group');
rootObject.remove(obj);// OR rootObject.add(obj);
What I observe is that to make change visible in scene, user needs to perform some action, like panning or zoomin/out etc.
How can change be made visible immediately without needing a manual action?
It looks like the scene is being redrawn not in the animation loop, but in some events (click, panning or zoomin/out, etc.).
So when adding or removing an object, you need to force a frame to be rendered. For example:
document
.getElementById('toggle')
.addEventListener('click', function() {
if (obj) {
removeObject()
} else {
addObject()
}
renderer.render(scene, camera);
})
[ https://jsfiddle.net/xmke5u20/ ]
I've followed the various animation tutorials on flutter.io, (tween, stagger, transitions, etc.) and its all great.
What I would like to explore is how to actually make custom animations based on the composition of a UI object.
Lets take a simple example, a Pause -> Play animation.
At first we have a Pause icon, two vertical bars.
Let's say I would like to
Grow the right bar into a triangle by adding an extra corner on the center of the rightmost vertical side, and moving it to the right.
After that moving that triangle from step 1 slightly to the left, so it now sticks to the leftmost vertical bar, into a bigger "triangle" (that'd be a pentagon actually).
That would look like a play button, and not a pause button anymore.
How would I achieve that kind of custom animation ? I'm assuming I can't work with the icons class. And I'm pretty sure I shouldn't do that with Widgets and just move them around.
Where would I go to start exploring that kind of precision in animations?
The answer from #Alaric points you at a couple of packages but doesn't really give any justification for why you'd use them.
The issue at hand is that the animation you're talking about is moderately complicated in terms of how it actually works. There are multiple items which change over time and possibly even become one bigger item.
There are two approaches you could take to solving this problem. The first is to use an external animation tool to create this animation, using whichever features the animation tool has to do item changing and merging. Then once you have an animation which runs to your satisfaction, you have to import it into your project somehow. That's where the fluttie and flare_flutter plugins come in - if you used Aftereffects, you use Lottie to export the file and then the fluttie plugin to show it. Flare is slightly simpler as it's meant for flutter, but you still create the animation externally and then add the file to your assets to be rendered.
The other approach is to do the animation yourself. That entails three things:
Creating a widget to contain the animation.
Creating a CustomPainter to actually draw the result.
Optionally, another class which acts as controller to start/stop/etc the animation.
The widget containing the animation could probably also be the controller if you use a GlobalKey to access it and expose start/stop methods, but that's a bit messy. It's better to have an external object that is the controller - and you could probably even use an AnimationController as-is although it would be less 'clean'.
If you don't pass it in, you'd probably have an AnimationController in your widget that you start and stop from your controller or class. It would essentially just go from 0 to 1 and back, and would be responsible for rebuilding the CustomPainter (probably using an AnimatedBuilder).
This is a very basic example that doesn't need an external controller as the gesture detection happens within the widget. Note that I'm not calling setState every time the 'started' member is set, because I don't actually want it to rebuild when it changes.
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: Center(
child: StartStop(),
),
),
);
}
}
class StartStop extends StatefulWidget {
#override
StartStopState createState() {
return new StartStopState();
}
}
class StartStopState extends State<StartStop> with TickerProviderStateMixin<StartStop> {
bool started = false;
AnimationController animationController;
#override
void initState() {
animationController = AnimationController(vsync: this, duration: Duration(milliseconds: 300));
super.initState();
}
#override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () {
started ? animationController.forward() : animationController.reverse();
started = !started;
},
child: SizedBox(
width: 100,
height: 100,
child: AnimatedBuilder(
animation: animationController,
builder: (context, child) {
return CustomPaint(
painter: StartStopPainter(animationController.value),
size: Size.infinite,
child: child,
);
},
),
),
);
}
}
class StartStopPainter extends CustomPainter {
final double percentAnimated;
StartStopPainter(this.percentAnimated) : assert(percentAnimated >= 0 && percentAnimated <= 1);
#override
void paint(Canvas canvas, Size size) {
var pausePaint = Paint()..color = Colors.black.withOpacity(1 - percentAnimated);
canvas.drawRect(Rect.fromLTRB(20, 10, 40, 90), pausePaint);
canvas.drawRect(Rect.fromLTRB(60, 10, 80, 90), pausePaint);
var playPaint = Paint()..color = Colors.black.withOpacity(percentAnimated);
canvas.drawPath(Path()..addPolygon([Offset(20, 10), Offset(20, 90), Offset(80, 50)], true), playPaint);
}
#override
bool shouldRepaint(CustomPainter oldDelegate) {
return true;
}
}
I'll leave the actual custom part of the animation (where you make the rectangle change to a triangle etc) to you. Instead of using opacity and a few different paint calls, you'd simply be using the input percentAnimated to decide which path or polygon to draw.
The default Qt3D OrbitCameraController's behavior is:
- Left mouse to move camera.
- Right mouse to rotate camera.
I need opposite solution, to simply rotate show a product model.
C++ code or AxisActionHandler maybe work, but I don't known how to write it. Thanks for help.
After trying different solutions, I used MouseHandler to finish this task. The core codes is below:
Entity{
id: root
property Camera camera;
MouseDevice {
id: mouseDevice
}
MouseHandler {
property point _lastPt; // 鼠标最后的位置
property real _pan; // 相机沿y轴旋转角度
property real _tilt; // 相机沿x轴旋转角度
on_PanChanged: root.camera.panAboutViewCenter(_pan);
on_TiltChanged: root.camera.tiltAboutViewCenter(_tilt);
sourceDevice: mouseDevice
onPressed: {_lastPt = Qt.point(mouse.x, mouse.y);}
onPositionChanged: mouseMove(mouse);
...
function mouseMove(mouse){
if (mouse.buttons == 1){
_pan = -(mouse.x - _lastPt.x);
_tilt = (mouse.y - _lastPt.y);
_lastPt = Qt.point(mouse.x, mouse.y);
}
}
}
}
I'm looking to animate a text field into view and a button out of view at the same time, so that it looks like the text field is replacing the button. (They are both equal size and take up the same area of the screen).
What's the best way to do this using React Native animation?
At this point, I am rendering the button if one of my state values is false, and the text field if it is true.
You can animate any style property in react-native using the Animated API.
If you are able to represent the changes in a sequence of style changes, the Animated API can do it. For instance animating the opacity from 1 to 0 and back to 1 will give a nice fade in fade out effect. The docs explain the Animations much more clearly
Also you can you selective rendering to mount or hide the component
<View style={{/*style props that need to be animated*/}}
{ boolShowText? <Text/> : <View/> }
</View>
The fading example as found in react-native docs
class FadeInView extends React.Component {
constructor(props) {
super(props);
this.state = {
fadeAnim: new Animated.Value(0), // init opacity 0
};
}
componentDidMount() {
Animated.timing( // Uses easing functions
this.state.fadeAnim, // The value to drive
{toValue: 1}, // Configuration
).start(); // Don't forget start!
}
render() {
return (
<Animated.View // Special animatable View
style={{opacity: this.state.fadeAnim}}> // Binds
{this.props.children}
</Animated.View>
);
}
}