Rotate coordinate System of an UIView - ios

Im a complete beginner, so please excuse my maybe stupid question.
Im using an UIView "superview" with many children-images to perform a rotation of the images around an arbitrary point:
superview.transform = CGAffineTransformMakeRotation(M_PI/2);
This works perfect, but it seems like this is rotating the coordinate system of the superview as well. This in turn messes up all following steps. I find hundreds of posts and infos concerning rotating images and for mac development there obviously is a method for rotating coordinate systems. I just don't find anything for iOS.
Is there a way to rotate a view without rotating the coord system / how can I rotate the coord system without influencing the images?
Thanks for any help.

it seems like this is rotating the coordinate system of the superview as well
You're right -- rotating the coordinate system of the superview is exactly what you're doing:
superview.transform = CGAffineTransformMakeRotation(M_PI/2);
Is there a way to rotate a view without rotating the coord system
Sure, just set the transform property for your view rather than for its superview. For any view someView, you can say:
someView.transform = CGAffineTransformMakeRotation(M_PI/2);
Note that this actually rotates the view's own coordinate system -- it doesn't rotate the view itself. That means that all your drawing will be rotated, but the view's frame will remain the same. You might need to adjust the frame to account for this. For example, if you have a rectangular view that's normally 100px high and 300px wide, you might want to make it 300px high and 100px wide to ensure that the content is all still visible.
If you're creating a custom view, you can of course refer to instances of that view from inside its own code using self:
self.transform = CGAffineTransformMakeRotation(M_PI/2);

Related

Spritekit - Bottom of screen coordinates

What are the coordinates for the bottom of the screen... or how can I create a "floor" at the bottom of the screen in spritekit?
Sorry, but I don't understand screen coordinates that well in spritekit.
You need to understand the Sprite Kit coordinate system as explained in Apple's Documentation here.
Here's how you create a floor at the bottom of the screen in SpriteKit:
SKNode *floor = [SKNode node];
node.physicsBody = [SKPhysicsBody bodyWithEdgeLoopFromRect:CGRectMake(CGRectGetMidX(self.frame),1.0 , CGRectGetWidth(self.frame), 1)];
[self addChild: floor];
You need some universal approach to get coordinates of corners on the screen.
Using code from that answer you can get CGRect with necessary information.
Example:
let screenRect = getVisibleScreen(
sceneRect: self.scene!.frame,
viewRect: self.view!.frame )
And then you can use it:
screenRect.minX
screenRect.maxX
screenRect.minY
screenRect.maxY
screenRect.width
screenRect.height
This is more then enough to calculate coordinates of "floor" or any other relative positions.
The location of the bottom of the screen will depend on what coordinate system you are using for your scene.
Out of the box, the bottom of the screen will be at y coordinate zero, but there are a few things that can happen that will affect that.
For instance, if you are using the scene editor in xCode, and your scene's anchorPoint property is something other than y=0, then the "origin" of your scene will not be at the bottom of the screen. In the recent xCode beta, they changed the default behavior to have the scene's origin at the center of the scene instead of the lower left corner, so that would explain why you might be seeing things in the center of the screen when you expect them to be at the bottom.
Also, the "bottom of the screen" will be relative to whatever parenting structure you have in your scene. For instance, if you place a background sprite in your scene, and want to attach a floor sprite to that which is at the bottom of the screen, you'll have to do some computing to figure out where to place it because you are going to inherit the translation and rotation of the floor's parent node (and any parents that node has).
To keep things simple, you can just place everything directly on the stage and manage their z-order manually. This will let you, basically, use the same coordinate system for everything. This is often fine; as long as you're not trying to do anything complex with your sprites, you don't need a complicated "tree" of nodes.
But even with this approach, the metrics of your scene are going to have to be handled dynamically. The width and height of your scene are going to depend on how you approach displaying your scene on different devices with different sizes. For instance, the top right of an iPhone 4 is going to be in a different place than the top right of an iPad Pro. A full discussion of how to deal with that is beyond the scope of your question, but generally, you'll probably want to use a "reference width" or a "reference height" for your scene, use .AspectFit or .AspectFill for the scaleMode, and set your scene's size accordingly. (I.e., inspect the view's frame to get the actual aspect ratio of your scene and set your scene size to match your reference metric on one axis and scale the other axis to match the device's aspect ratio.) This will let you use the same metrics for all devices (although one of your two axes will be fluid).

Rotate Image on Slider Value in iOS

I am rotating the image on slider value -
I am using this code for rotation -
editingView.transform = CGAffineTransformRotate(editingView.transform,sliderVal);
its Rotating properly but if i am trying to move or resize after rotation,The editingView is resizing with unexpected behavior and view disappears from screen.
Please suggest me what i am doing wrong.
Well whenever you rotate a view which is inside a superview, you should preserve the position of the view. If you are not rotating any view across the origin then, you should first translate the view's origin to the superview's origin and then rotate and then again translate back to the original point.
Find the coordinate if the view you want to rotate with respect to its superview, say it (x,y).
Translate the view to the origin as;
view.transform = CGAffineTransformMakeTranslation(x,y)
Rotate the view by some angle, say PI,
view.transform = CGAffineTransformMakeRotation(PI)
After rotation translate back to the original point as;
view.transform = CGAffineTransformMakeTranslation(-x,-y)
And that's it. It should work with all the different rotation.
Have a look at this question.
Since you do not show any code on how you do the move or resizing, I suspect you are not properly concatenating the transforms. Furthermore, after you did the rotation, a translation will possibly work on the rotated coordinate system, therefore leading to unexpected behaviour.
Changing transform value affecting the frame value of UIView. As Apple says:
Warning: If this property is not the identity transform, the value of
the frame property is undefined and therefore should be ignored.
Apple docs
So, if you are moving or resizing your view using frame property, try do this with bounds, center properties

Getting the same coordinates from UIScrollView whether it's zoomed or not

Is it possible to get the same coordinates from UIScrollView whether it's zoomed or not.
That is, For example, consider a plain screen of 320.0F and 480.0F.
Tap on a point; view will give me something like (60.0F, 80.0F).
Zooming-in or zooming-out on the view so that it will have either bigger or smaller zoom scale but making sure the zoomed area to contain the point that was tapped which was (60.0F, 80.0F) according to previous zoom scale.
Tap on the point again, the view will give me different coordinate value.
The Thing is, I want to have the same coordinate value whether the view is zoomed or not. The idea is simple. I want to show images zoomed & interactive without changing its coordinate. Considering an UIScrollView applied of the idea with its height of 1.0 and width of 0.66, I think there would be some pros programming this way, when making an interactive app without using OpenGL, cocos2d or whatever 3D engines out there.
Do you guys have any idea if it's supported or not? Either case, please don't wait any second to reply. Thanks
You can calculate it by yourself using content size as follows,
x = (original_Width/ width_after_zooming) * point.x
y = (original_height/ height_after_zooming) * point.y

UIView: how to "reset" transformations. CGAffineTransformScale not working as I would expect

I think my question can be summed up as how to store and reset the transform of a view. But then perhaps explaining my situation might help.
If I apply the transforms below to a view, one after another (like if I add this code to a switch or a button). I get exactly the result I would expect: the scale switches between: a view that is .55 times the size of the original view, and the view at it's original scale. Works to scale sub-views of someView too, just as I want. Ad infinitum. Perfect.
//tranformScale 1
someView.transform = CGAffineTransformScale(CGAffineTransformIdentity, 0.55, 0.55 );
//tranformScale 2
someView.transform = CGAffineTransformScale(CGAffineTransformIdentity, 1.0, 1.0 );
The trouble is I want to use this code (or similar) to scale a sub-view of self.view when an iOS device goes into landscape, to fit the sub-view to the landscape screen (and back up when in portrait). It almost works, but for some reason instead of outputting round values values for the frame of the view being scaled (as happens with a test using a button to call the transforms), progressively strange values are produced. Eventually, after about 4 rotations the sub-view flies off screen. I suspect it has to do with self.view changing shape, but then again, when I log the frame of self.view it's shape is very predictable.
By the way I am centering the view using autoresizingMask flexible margins, not using auto-layout. perhaps I should be centering the view with another type of calculation?
Thanks for reading!
I did this and it worked perfect.
self.imageview.transform = CGAffineTransformIdentity
(1) be sure not to set or get any frame data after applying transforms, it is unsupported and will yield unpredictable results;
(2) turn off your autoresizing mask flex margins and center like this:
view.center = CGPointMake(view.superview.bounds.size.width/2,
view.superview.bounds.size.height/2);
(take care to apply centering while view is at full size. i.e. BEFORE the transform if it is the resize transform, AFTER the transform if it is the identity transform)

Move a UIImageView after applying CGAffineTransformRotate behave incorrect

I'm trying to rotate UIImageView for certain degrees with CGAffineTransformMakeRotation() function, but it end with imageView only rotates, but when I moved to another coordinates then imageView stretched or change height and width. I have no clue why this happens.
Here is a code:
double a = atan2(dx,dy);
bowImageView.transform = CGAffineTransformMakeRotation(a);
WHen you apply a transform to a view the geometry changes. If you wish to move that view rotated, the simplest solution is to set the transform back to CGAffineTransformIdentity, move the view and reapply the rotation.
The other way is to work out the movement based on the current rotation.....but I find the first solution easier!

Resources