I can flip my view by doing something like this:
image.transform = CGAffineTransformMakeScale(-1, 1);
My problem is if I have scaled the item in the app this code obviously sends it back to its original size and flips it. How can I maintain the current scale and flip the object?
Get the context's current transformation matrix (CTM), and apply your flipping transform to that matrix.
Related
I want to ask a question about the perspective that is achieved through CATransform3D.
I know that if you have a view that is 320x480 and then apply this:
CATransform3D perspective = CATransform3DIdentity;
CGFloat zDistance = 1000;
perspective.m34 = 1.0 / -zDistance;
view.layer.sublayerTransform = perspective;
you create a perspective that makes it look like the observer is looking straight at the center of the screen and therefore the same transformation looks different, depending on where the subview that is being transformed is located on the screen. For example, tilting a view looks like this when the view is in the middle of the screen:
And it looks like this if it's in the lower left corner:
Now, my problem is that making the perspective relative to the screen only works if the view I'm transforming is a subview of another view that is 320x480px big. But what if the view I want to transform is a subview of a view that is only 100x100px? Is there a way to make the perspective relative to the whole screen if the superview isn't the size of the screen?
Thanks in advance
According to apple
"The anchorPoint property is a CGPoint that specifies a location within the bounds of a layer that corresponds with the position coordinate. The anchor point specifies how the bounds are positioned relative to the position property, as well as serving as the point that transforms are applied around."
Your perspective should not be relative to the center of the screen or even to the center of your layer by default, is that where you have your anchor point? Aside from that though, what you seem to be asking is how to make your perspective appear to be relative to a different point. The trick is that your perspective is created by multiplying by your perspective matrix. Setting m34 to a small number does nothing magic, you are multiplying by your projection matrix.
YourProjection = {1,0,0 ,0,
0,1,0 ,0,
0,0,1 ,0,
0,0,-1.0/zdistance,1};
Remember that you can combine successive transforms by multiplying them together. Just transform your layer to wherever you want, then apply your Projection matrix, then transform it back, presto, perspective from a different origin.
float x = your coordinates relative to the screen center;
float y = same thing
TranslationMatrix = {1,0,0,0,
0,1,0,0,
0,0,1,0,
x,y,0,1};
ReverseTranslationMatrix = {1,0,0,0,
0,1,0,0,
0,0,1,0,
-x,-y,0,1};
//now just multiply them all together
Final = ReverseTranslation*YourProjection*Translation;
You will need to do the matrix math yourself, hopefully you already have a generic 4x4 column major matrix class that can do multiplication for you, if not i suggest you make one. Also, if you are interested, you might consider reading. This for an explanation of how the matrix you are currently using works, or This for a different take on projection matrices.
I need to change the size of my images according to their distance from the center of the screen. If an image is closer to the middle, it should be given a scale of 1, and the further it is from the center, the nearer it's scale is to zero by some function.
Since the user is panning the screen, I need a way to change the images (UIViews) scale, but since this is not a very classic animation where I know a how to define an animation sequence exactly - mostly because of timing issues (due to system performance, I don't know how long the animation will last), I am going to need to simply change the scale in one step (no timed animations).
This way every frame the functiion gets called when panning, all images should update easily.
Is there a way to do that ?
You could directly apply a CGAffineTransform to your UIImageView. i,e:
CGAffineTransform trans = CGAffineTransformMakeScale(1.0,1.0);
imageView.transform = trans;
Of course you can change your values, and or use other CGAffineTransform's, this should get you on your way though.
Hope it helps !
I'm implementing a basic speedometer using an image and rotating it. However, when I set the initial rotation (at something like 240 degrees, converted to radians) It rotates the image and makes it much smaller than it otherwise would be. Some values make the image disappear entirely. (like M_PI_4)
the slider goes from 0-360 for testing.
the following code is called on viewDidLoad, and when the slider value is changed.
-(void) updatePointer
{
double progress = testSlider.value;
progress += pointerStart
CGAffineTransform rotate = CGAffineTransformMakeRotation((progress*M_PI)/180);
[pointerImageView setTransform:rotate];
}
EDIT: Probably important to note that once it gets set the first time, the scale remains the same. So, if I were to set pointerStart to 240, it would shrink, but moving the slider wouldn't change the scale (and it would rotate it as you'd suspect) Replacing "progress" with 240 in the transformation does the same thing. (shrinks it.)
I was able to resolve the issue for anybody who stumbles across this question. Apparently the image is not fully loaded/measured when viewDidLoad is called, so the matrix transforms that cgAffineTransform does actually altered the size of the image. Moving the update code to viewDidAppear fixed the problem.
Take the transform state of the view which you want to rotate and then apply the rotation transform to it.
CGAffineTransform trans = pointerImageView.transform;
pointerImageView.transform = CGAffineTransformRotate(trans, 240);
Open GL ES coordinates are flipped on the y axis compared to iOS. Saving the data out via glreadpixels (to a video) gives me the proper transformation, but displaying in a UIView has the y axis flipped. What is the best way to flip it back for presentation?
I'm seeing three ways so far:
1) Render twice in opengl, sending the non-flipped version to glreadpixels, and a flipped version to the CAEAGLLayer (presentRenderbuffer).
2) Flip the pixels in opengl so it displays properly; once I've read them via glreadpixels, shift the bits then save that to file.
3) Flip the pixels in opengl so it displays properly; apply some type of transform on the video itself (causing it to flip at the time of playback).
I'm not sure any of these are the right path. Looking for the most performant path.
Just apply a transform to the UIView to flip it. For example:
view.transform = CGAffineTransformMakeScale(1.0, -1.0);
Looks like the best way is by using flipped vertices in opengl.
I am trying to figure out how can you drag an image while constraining its movement along a certain path.
I tried several tricks including animation along a path, but couldn't get the animation to play and pause and play backwards - so that seems out of the question.
Any ideas ? anyone ?
What you're basically trying to do is match finger movement to a 'translation' transition.
As the user touches down and starts to move their finger you want to use the current touch point value to create a translation transform which you apply to your UIImageView. Here's how you would do it:
On touch down, save the imageview's starting x,y position.
On move, calculate the delta from old point to new one. This is where you can clamp the values. So you can ignore, say, the y change and only use the x deltas. This means that the image will only move left to right. If you ignore the x and use y, then it only moves up and down.
Once you have the 'new' calculated/clamped x,y values, use it to create a new transform using CGAffineTransformMakeTranslation(x, y). Assign this transform to the UIImageView. The image moves to that place.
Once the finger lifts, figure out the delta from the original starting x,y, point and the lift-off point, then adjust the ImageView's bounds and reset the transform to CGAffineTransformIdentity. This doesn't move the object, but it sets it so subsequent accesses to the ImageView use the actual position and don't have to keep adjusting for transforms.
Moving along on a grid is easy too. Just round out the x,y values in step 2 so they're a multiple of the grid size (i.e. round out to every 10 pixel) before you pass it on to make the translation transform.
If you want to make it extra smooth, surround the code where you assign the transition with UIView animation blocks. Mess around with the easing and timing settings. The image should drag behind a bit but smoothly 'rubber-band' from one touch point to the next.
See this Sample Code : Move Me