I'm trying to make an animated sine wave similar to this solution:
https://stackoverflow.com/a/17535290
I'm trying to make my sine wave continuous so that I'm constantly drawing the same sine wave. In the solution above, once the starting point of the wave is equal to the width of the frame, the view restarts drawing a new wave.
Can someone explain what CGAffineTransformMakeTranslation(+_self_view.frame.size.width/2, 0); does in the code below? My understanding is that it returns a matrix that shifts the x-axis to the right by half the frame size. I don't understand how that causes the animation to do what it does.
-(void)animateWave {
[UIView animateWithDuration:.5 delay:0.0 options:UIViewAnimationOptionRepeat|UIViewAnimationOptionCurveLinear animations:^{
_self_view.transform = CGAffineTransformMakeTranslation(+_self_view.frame.size.width/2, 0);
} completion:^(BOOL finished) {
_self_view.transform = CGAffineTransformMakeTranslation(0, 0);
}];
}
There are two views involved. There is the “sine wave” view, and there is the superview (parent) of the sine wave view.
Suppose the superview is 320 points wide - the width of the iPhone screen.
Make the sine wave view 640 points, and draw two cycles of the sine wave in it. Each cycle is exactly 320 points wide. Thus the left 320 points of the sine wave view look exactly like the right 320 points.
Now position the sine wave view in its superview with a frame.x of -320. This means only the right 320 points of the sine wave view are visible:
Now animate the sine wave view to the right by 320 points (half of its width):
When the animation finishes, the visible part of the sine wave view looks identical to the part that was visible before the animation:
If at this point you reset the sine wave view to its initial position (instantly, without animation), the user won't be able to tell, because the visible pixels won't change:
The effect of UIViewAnimationOptionRepeat is to reset the animated parameters to their original states and then start the animation over. Thus if you arrange the sine wave view and its superview as I described, you will get a seamless loop.
Your understanding is correct. Here, the idea is to place the origin at the center of view. Try this, do you see any difference?
CGSize size = self.bounds.size;
CGAffineTransform translate = CGAffineTransformMakeTranslation(size.width / 2, size.height / 2);
Related
I have a UIView in my view. Right now I have a button moving the UIView on it's y axis. Here is my code
CGRect frame2 = self.test22.frame;
frame2.origin.y -= 1.f/[UIScreen mainScreen].scale; //however many pixels to the right..
self.test22.frame = frame2;
But how can I rotate it? Except using the x or y axis. I want to be able to move the UIView by rotation by 1.f.
To Rotate the UIView create the object of UIView (*view) and make transform on it
Lets to rotate the view 90 degree use below code
CGAffineTransform r_transform = CGAffineTransformIdentity;
r_transform = CGAffineTransformRotate(r_transform,DegreeYoRadians(90));
view.transform = r_transform;
Welcome to SO. You want to look at the UIView method animateWithDuration, and the view's transform property. You'd apply a rotation transform to the view in your animation block. Note that if you change a view's transform, you should not read or write the frame property. Instead use the center property to change the position and the bounds.size property if you need to change the size.
Your code might look like this:
[UIView animateWithDuration: .25
animations: ^
{
self.test22.transform = CGAffineTransformMakeRotation(M_PI/2);
CGPoint center = self.test22.center;
center.y -= 1;
self.test22.center = center;
}
];
EDIT:
I have no idea what you mean when you say "I want to be able to move the UIView by rotation by 1.f." Rotating a view is not moving it, it's rotating it. And rotation is expressed as an angle, not a value like "1". Furthermore, the angle is in radians, where π is 180 degrees, π/2 is 90 degrees, and 2π is a full-circle rotation (or no change, since it puts the rotation back at it's original value.) You have to think in terms of fractions of 2π when you do rotations. Or you can use degrees and convert to radians, where:
degrees = radians * 180/π
Also, your code that moves the view will only change the view's position by half a point on retina displays which doesn't make much sense.
I have a view containing many bubbles of various sizes. I am trying to create an animation that will zoom into a bubble, making it the same size every time, and center it in my view. This would cause all the bubbles to zoom until the bubble in question is the right size. The bubbles should all maintain the same ratio throughout the process so that if one bubble moves, all the others move the same amount and in the same direction. If one grows, they all grow in proportion.
I have gotten as far as creating the animation to center the bubble and all the other bubbles move proportionally. The problems arise when I try to make the bubbles grow. Once I add the line bellow which does successfully make the bubbles grow in proportion, the code to move the bubble to center the bubbles no longer moves the bubble to the right point. I cannot figure out how to make the bubble both grow and move to the right position.
To move the bubbles (Needs to be 22p from the top and centered horizontally, and 64p by 64p in size), this successfully moves the bubbles to the right position without growing them to the correct size:
float distanceFromTop = 22 - bubble.frame.origin.y;
float distanceFromLeft = self.frame.size.width / 2 - bubble.center.x;
[UIView animateWithDuration:1 animations:^{
self.currentKarmaView.frame = CGRectMake(distanceFromLeft, distanceFromTop, self.currentKarmaView.frame.size.width, self.currentKarmaView.frame.size.height);
}];
To make the bubbles grow, I added the following line, which should make the bubbles grow and move them to the right position. With growth added, the bubbles still move, just not to the right position.
float distanceFromTop = 22 - bubble.frame.origin.y;
float distanceFromLeft = self.frame.size.width / 2 - bubble.center.x;
[UIView animateWithDuration:1 animations:^{
self.currentKarmaView.frame = CGRectMake(distanceFromLeft, distanceFromTop, self.currentKarmaView.frame.size.width, self.currentKarmaView.frame.size.height);
self.currentKarmaView.transform = CGAffineTransformScale(CGAffineTransformIdentity, scaleFactor, scaleFactor);
}];
I have tried many many variations of this, but cannot get the growth and positioning to work in unison. If anyone can help, I would really appreciate it.
I'm trying to 3D animate an UIImageView on X axis so it will do a 180 degrees rotation. At 90 degres I want to change the image. (that is why i "broke" the animation in 2).
Animation works well, but the problem is that the second image is drawn upside down. Any ideas what should i do for the image to be drawn normal?
Here is my code
i++;
[UIView animateWithDuration:2 animations:^{
self.imageView.layer.transform = CATransform3DMakeRotation(-M_PI/2 , 1, 0,0);
} completion:^(BOOL finished){
UIImage *bottomI = (UIImage *)[bottom objectAtIndex:i];
self.second.image =bottomI;
[UIView animateWithDuration:2 animations:^{
imageView.layer.transform = CATransform3DMakeRotation(M_PI , 1, 0,0);
} completion:^(BOOL finised){
}];
}];
What I've done (using grouped CABasicAnimation objects instead of view animations, but the same trick should work) is to rotate the view/layer the first 90 degrees, then rotate it 180 degrees without animation before starting the second half of the animation. That way, the second half of the animation actually causes the front face of the view/layer to rotate into view as if it was the back face, but not backwards.
The view/layer is edge-on to the viewer while you are switching it's image and rotating it 180 degrees, so the user can't see those changes. When it rotates the remaining 90 degrees, the new image is in place and it appears to be revealing the back side of the view/layer.
It works perfectly.
When you are 3d rotating a view, it is similar to rotating an object in real life. So, once the rotation is more than 90 degrees, it would invert the object. Which is why your second image is inverted. The simplest thing to do is to set the affine transform of the image to rotate it by 180 degrees before adding it in.
EDIT: My silliness....
What I intended was this
bottomI.orientation = UIImageOrientationDown
I am playing with the deferent animations using the alpha C4 framework.
I am trying to shape grow from the midel of the canvas till it covers it completely....Is there any animation that can create that zoom effect?
Yup, you can change and animate a C4Shape like this:
shape.animationDuration = 1.0f; //1 second animation duration
[shape rect:(-1,-1,769,1025)];
Note, the above is for a rectangle that will be 1px larger than the screen of an iPad on all sides. To make an ellipse you'd have to figure out the size of the frame that will encompass an ellipse that covers the whole screen.
I want to simultaneously scale and translate a CALayer from one CGrect (a small one, from a button) to a another (a bigger, centered one, for a view). Basically, the idea is that the user touches a button and from the button, a CALayer reveals and translates and scales up to end up centered on the screen. Then the CALayer (through another button) shrinks back to the position and size of the button.
I'm animating this through CATransform3D matrices. But the CALayer is actually the backing layer for a UIView (because I also need Responder functionality). And while applying my scale or translation transforms separately works fine. The concatenation of both (translation, followed by scaling) offsets the layer's position so that it doesn't align with the button when it shrinks.
My guess is that this is because the CALayer anchor point is in its center by default. The transform applies translation first, moving the 'big' CALayer to align with the button at the upper left corner of their frames. Then, when scaling takes place, since the CALayer anchor point is in the center, all directions scale down towards it. At this point, my layer is the button's size (what I want), but the position is offset (cause all points shrank towards the layer center).
Makes sense?
So I'm trying to figure out whether instead of concatenating translation + scale, I need to:
translate
change anchor point to upper-left.
scale.
Or, if I should be able to come up with some factor or constant to incorporate to the values of the translation matrix, so that it translates to a position offset by what the subsequent scaling will in turn offset, and then the final position would be right.
Any thoughts?
You should post your code. It is generally much easier for us to help you when we can look at your code.
Anyway, this works for me:
- (IBAction)showZoomView:(id)sender {
[UIView animateWithDuration:.5 animations:^{
self.zoomView.layer.transform = CATransform3DIdentity;
}];
}
- (IBAction)hideZoomView:(id)sender {
CGPoint buttonCenter = self.hideButton.center;
CGPoint zoomViewCenter = self.zoomView.center;
CATransform3D transform = CATransform3DIdentity;
transform = CATransform3DTranslate(transform, buttonCenter.x - zoomViewCenter.x, buttonCenter.y - zoomViewCenter.y, 0);
transform = CATransform3DScale(transform, .001, .001, 1);
[UIView animateWithDuration:.5 animations:^{
self.zoomView.layer.transform = transform;
}];
}
In my test case, self.hideButton and self.zoomView have the same superview.