while performing dual operation on UIImageView - ios

This time I am facing problem while performing dual operation on UIImageView means
1) Zoom+Flip the Image
2)Zoom + Reverse the Image
3)Zoom + Flip or Reverse + Rotate(+- 90)deg
so please help to find out the solution of this problem. In thiscase for Zoom I use the GuestureRecognizer for fliping+Revesing+Rotating UIImageView I Use the the UIButton for these operation so how I can handle these operations wiith combination on UIImage
what exact the problem When I Zoom In or Zoom Out the image the at the same time I want to rotate (+-90 deg) or Flip or Reverse the Image at exact zoom In or Zoom Out Position but that time Image get reset then perform the respective operation such rotate, flip ,reverse I wanted to do it simultaneously on UIImage
my code as
if (btnNames == "Rotate R")
{
Angle = deg + 90;
imgview.Transform = CGAffineTransform.MakeRotation (Angle * (float)Math.PI / 180);
return Angle;
} else
{
Angle = deg - 90;
imgview.Transform = CGAffineTransform.MakeRotation (Angle * (float)Math.PI / 180);
return Angle;
}
For Reverse
CGAffineTransform transform = CGAffineTransform.MakeScale (-1, 1);
imgView.Transform = transform;
return true;
============
For Flip
if (flips == false)
{
CGAffineTransform transform = CGAffineTransform.MakeScale (1, -1);
imgView.Transform = transform;
return true;
}
this code i implemented it works fine individually perform to operation. But I want to work simultaneously on UIImage

I would recommend:
Place the UIImage in a UIScrollView with zooming setup
Modify your UIImage's Transform for reverse, rotate, etc.
To setup zooming:
yourScroller.MaximumZoomScale = 5;
yourScroller.MinimumZoomScale = 1;
yourScroller.ViewForZoomingInScrollView = _ => yourImage;
An example for rotation would be:
yourImage.Transform.Rotate (Math.PI / 2)
Play around with it, the UIScrollView should modify the same Transform on the image, so everything should work in tandem.

I'm not sure I really understand what you mean, but it sounds like your trying to do more the one transformations for an image by setting the UIView's transform property like this (example):
myView.transform = scale;
myView.transform = flip;
myView.transform = rotate;
What happens then is, that only the last one of these "is active: on the view.
What you should do is "keeping/saving" the current transformation and appending the new one with CGAffineTransformConcat like:
myView.transform = scale;
myView.transform = CGAffineTransformConcat(myView.transform, flip);
myView.transform = CGAffineTransformConcat(myView.transform,rotate);
Keep in mind that for some transformations order of concatenation matters!

Transformations can be combined by applying them to an existing transformation:
CGAffineTransform transform = CGAffineTransformIdentity;
// Rotate
if (btnNames == "Rotate R") {
Angle = deg + 90;
transform = CGAffineTransformRotate(transform, Angle * (CGFloat)Math.PI / 180);
} else {
Angle = deg - 90;
transform = CGAffineTransformRotate(transform, Angle * (CGFloat)Math.PI / 180);
}
// Reverse
transform = CGAffineTransformScale(transform, -1, 1);
// Flip
if (!flips) {
transform = CGAffineTransformScale(transform, 1, -1);
}
// Apply combined transformation
imgView.transform = transform;

Related

how do I make the base of each UIView a tangent to a circle so they radiate from the centre?

I am trying to find angles of rotation for a series of light and dark rectangular UIViews placed at regular points on a circle perimeter. Each point on the circle is calculated as an angle of displacement from the centre and I have tried using the same angle to rotate each UIView so it radiates from the centre. But I didn't expect it to look like this.
I expected the angle of displacement from the centre to be the same as the angle of rotation for each new UIView. Is this assumption correct ? and if so, how do I make the base of each UIView a tangent to a circle so they radiate from the centre ?
UPDATE
In case someone finds it useful here is an update of my original code. The problem as explained by rmaddy has been rectified.
I’ve included two versions of the transform statement and their resulting rotated UIViews. Result on the left uses radians + arcStart + M_PI / 2.0, result on right uses radians + arcStart.
Here is the method.
- (void)sprocket
{
CGRect canvas = [UIScreen mainScreen].bounds;
CGPoint circleCentre = CGPointMake((canvas.size.width)/2, (canvas.size.height)/2);
CGFloat width = 26.0f;
CGFloat height = 50.0f;
CGPoint miniViewCentre;
CGFloat circleRadius = 90;
int miniViewCount = 16;
for (int i = 0; i < miniViewCount; i++)
{
// to place the next view calculate angular displacement along an arc
CGFloat circumference = 2 * M_PI;
CGFloat radians = circumference * i / miniViewCount;
CGFloat arcStart = M_PI + 1.25f; // start circle from this point in radians;
miniViewCentre.x = circleCentre.x + circleRadius * cos(radians + arcStart);
miniViewCentre.y = circleCentre.y + circleRadius * sin(radians + arcStart);
CGPoint placeMiniView = CGPointMake(miniViewCentre.x, miniViewCentre.y);
CGRect swivellingFrame = CGRectMake(placeMiniView.x, placeMiniView.y, width, height);
UIView *miniView = [[UIView alloc] initWithFrame:swivellingFrame];
if ((i % 2) == 0)
{
miniView.backgroundColor = [UIColor darkGrayColor];
}
else
{
miniView.backgroundColor = [UIColor grayColor];
}
miniView.layer.borderWidth = 1;
miniView.layer.borderColor = [UIColor blackColor].CGColor;
miniView.layer.cornerRadius = 3;
miniView.clipsToBounds = YES;
miniView.layer.masksToBounds = YES;
miniView.alpha = 1.0;
// using the same angle rotate the view around its centre
miniView.transform = CGAffineTransformRotate(miniView.transform, radians + arcStart + M_PI / 2.0);
[page1 addSubview:miniView];
}
}
The problem is your calculation of the center of each miniView is based on radians plus arcStart but the transform of each miniView is only based on radians.
Also note that angle 0 is at the 3 o'clock position of the circle. You actually want a 90° (or π/2 radians) rotation of miniView so the rectangle "sticks out" from the circle.
You need two small changes to make your code work:
Change the loop to:
for (int i = 0; i < miniViewCount; i++)
And change the transform:
miniView.transform = CGAffineTransformRotate(miniView.transform, radians + arcStart + M_PI / 2.0);

How to rotate image view while not changing center X position

I want to rotate my image view using following:
CGFloat degrees = -20.0f; //the value in degrees
CGFloat radians = degrees * M_PI/180;
_arrowImgView.transform = CGAffineTransformMakeRotation(radians);
It does rotate, but unfortunatelly it does rotate whole image moving it up. Please take a look at screenshots:
On second screenshot you can see that image is moved up and changed X coordinate. How to simply bend it like clock arrow?
UPDATED:
I changed code to:
self.arrowImgView.layer.anchorPoint = CGPointMake(0.0f, 0.0f);
CGFloat degrees = -20.0f; //the value in degrees
CGFloat radians = degrees * M_PI/180;
self.arrowImgView.transform = CGAffineTransformMakeRotation(radians);
Also i want to notice that i did set constraints like that :
[_arrowImgView mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.bottom.equalTo(self);
make.centerX.equalTo(self.mas_centerX);
}];
Try this code
imageView.layer.anchorPoint = CGPointMake(0.0f, 0.0f);
imageView.transform = CGAffineTransformMakeRotation(angle);
Reference: https://developer.apple.com/reference/quartzcore/calayer/1410817-anchorpoint
Edit
I tried this below code in swift it works here
self.viewRotate.layer.anchorPoint = CGPoint(x: 0, y: 0)
let degree : CGFloat = -20.0
let rad : CGFloat = degree*CGFloat(M_PI/180)
viewRotate.transform = CGAffineTransform(rotationAngle: rad)
Output
Before rotation
After rotation

How to rotate UIView using transform?

I have a UIView which I am trying to transform (rotate) using the pitch value you can get from coremotion attitude. I am using transform however I am not sure my code is correct as the UIView is not doing anything.
This is my code its being called several times per second.
- (void)setLabelValueRoll:(double)roll pitch:(double)pitch yaw:(double)yaw
{
self.yLabel.text = [NSString stringWithFormat:#"pitch: %f", pitch];
CATransform3D transform;
transform = CATransform3DMakeRotation(pitch + M_PI_2, 1, 0, 0);
self.wapaA.layer.sublayerTransform = transform;
}
I am not sure how to set this part (pitch + M_PI_2, 1, 0, 0) to make the pitch affect my square UIView so it would I guess stay level as you tilt the phone back and forth.
It should be layer's transform property of UIView
wapaA.layer.transform = CATransform3DMakeRotation(pitch + M_PI_2, 1, 0, 0);
This will work
float degrees = 20; //the value in degrees
view.transform = CGAffineTransformMakeRotation(degrees * M_PI/180);

UISliders overlap after transforming

I'm currently trying to create four vertical sliders in Objective-C. I'm able to rotate them using CGAffineTransform, but right now each slider is stacked on top of one another. How do you change the coordinates of the sliders so this doesn't happen?
Below is my code for rotating the sliders:
CGAffineTransform trans1 = CGAffineTransformMakeRotation(M_PI * 1.5);
_grainPitchSlider.transform = trans1;
CGAffineTransform trans2 = CGAffineTransformMakeRotation(M_PI * 1.5);
_grainOffsetSlider.transform = trans2;
CGAffineTransform trans3 = CGAffineTransformMakeRotation(M_PI * 1.5);
_grainDensitySlider.transform = trans3;
CGAffineTransform trans4 = CGAffineTransformMakeRotation(M_PI * 1.5);
_grainDurationSlider.transform = trans4;
Simply set the "center" of each slider, i.e. _grainPitchSlider.center = CGPointMake(x, y);

Is there a way to calculate the CGAffineTransform needed to transform a view from frame A to frame B?

Say, I have two CGRects, CGRect A and CGRect B. My UIView's frame is the same as CGRect B, but I want to create an animation showing the UIView transitioning from frame A to B.
I'm trying to do this by changing the transform property of the UIView, so I don't have to mess around with its frame too much. However, I need the CGAffineTransform to make this possible. What is the best way to calculate this transform?
The previous answers didn't work for me. This should work:
Swift 5 (extension)
extension CGAffineTransform {
init(from source: CGRect, to destination: CGRect) {
self = CGAffineTransform.identity
.translatedBy(x: destination.midX - source.midX, y: destination.midY - source.midY)
.scaledBy(x: destination.width / source.width, y: destination.height / source.height)
}
}
Swift 4
func transformFromRect(from source: CGRect, toRect destination: CGRect) -> CGAffineTransform {
return CGAffineTransform.identity
.translatedBy(x: destination.midX - source.midX, y: destination.midY - source.midY)
.scaledBy(x: destination.width / source.width, y: destination.height / source.height)
}
Swift
func transformFromRect(from: CGRect, toRect to: CGRect) -> CGAffineTransform {
let transform = CGAffineTransformMakeTranslation(CGRectGetMidX(to)-CGRectGetMidX(from), CGRectGetMidY(to)-CGRectGetMidY(from))
return CGAffineTransformScale(transform, to.width/from.width, to.height/from.height)
}
Objective-C
+ (CGAffineTransform) transformFromRect:(CGRect)sourceRect toRect:(CGRect)finalRect {
CGAffineTransform transform = CGAffineTransformIdentity;
transform = CGAffineTransformTranslate(transform, -(CGRectGetMidX(sourceRect)-CGRectGetMidX(finalRect)), -(CGRectGetMidY(sourceRect)-CGRectGetMidY(finalRect)));
transform = CGAffineTransformScale(transform, finalRect.size.width/sourceRect.size.width, finalRect.size.height/sourceRect.size.height);
return transform;
}
I haven't been able to find a convenience method of any kind for this, so I resorted to tried and true matrix calculations to achieve this.
Given a CGRect A and CGRect B, to calculate the transformation needed to go from A to B, do the following:
CGAffineTransform transform = CGAffineTransformTranslate(CGAffineTransformIdentity, -A.origin.x, -A.origin.y);
transform = CGAffineTransformScale(transform, 1/A.size.width, 1/A.size.height);
transform = CGAffineTransformScale(transform, B.size.width, B.size.height);
transform = CGAffineTransformTranslate(transform, B.origin.x, B.origin.y);
A nice Swift 3 solution:
extension CGAffineTransform {
init(from: CGRect, toRect to: CGRect) {
self.init(translationX: to.midX-from.midX, y: to.midY-from.midY)
self = self.scaledBy(x: to.width/from.width, y: to.height/from.height)
}
}
Here's a variation on josema.vitaminew answer that also considers aspect ratio (useful if you are working with videos or images):
+ (CGAffineTransform)transformFromRect:(CGRect)sourceRect toRect:(CGRect)finalRect keepingAspectRatio:(BOOL)keepingAspectRatio {
CGAffineTransform transform = CGAffineTransformIdentity;
transform = CGAffineTransformTranslate(transform, -(CGRectGetMidX(sourceRect)-CGRectGetMidX(finalRect)), -(CGRectGetMidY(sourceRect)-CGRectGetMidY(finalRect)));
if (keepingAspectRatio) {
CGFloat sourceAspectRatio = sourceRect.size.width/sourceRect.size.height;
CGFloat finalAspectRatio = finalRect.size.width/finalRect.size.height;
if (sourceAspectRatio > finalAspectRatio) {
transform = CGAffineTransformScale(transform, finalRect.size.height/sourceRect.size.height, finalRect.size.height/sourceRect.size.height);
} else {
transform = CGAffineTransformScale(transform, finalRect.size.width/sourceRect.size.width, finalRect.size.width/sourceRect.size.width);
}
} else {
transform = CGAffineTransformScale(transform, finalRect.size.width/sourceRect.size.width, finalRect.size.height/sourceRect.size.height);
}
return transform;
}
The last line in the above code snippet needs to be changed as follows:
transform = CGAffineTransformTranslate (transform, B.origin.x*A.size.width/B.size.width, B.origin.y*A.size.height/B.size.height);
I started to use Kanobius answer, but either I'm misunderstanding his use of the term "aspect ratio" or he is, because it didn't perform as I expected. Here's my version that keeps the aspect ratio of the original view (by applying the scaling to both H and W) to achieve an "aspect fit" behavior
+ (CGAffineTransform)transformFromRect:(CGRect)sourceRect toRect:(CGRect)finalRect keepingAspectRatio:(BOOL)keepingAspectRatio
{
CGAffineTransform transform = CGAffineTransformIdentity;
// since the scale transform works around the midpoints, align them before doing the transform.
transform = CGAffineTransformTranslate(transform, -(CGRectGetMidX(sourceRect)-CGRectGetMidX(finalRect)), -(CGRectGetMidY(sourceRect)-CGRectGetMidY(finalRect)));
CGFloat originalHeight = sourceRect.size.height;
CGFloat scaledHeight = finalRect.size.height;
CGFloat hScalePercentage = scaledHeight / originalHeight;
CGFloat originalWidth = sourceRect.size.width;
CGFloat scaledWidth = finalRect.size.width;
CGFloat wScalePercentage = scaledWidth / originalWidth;
if (keepingAspectRatio)
{
CGFloat scalePercentage = MIN(hScalePercentage, wScalePercentage); // the most amount of scaling == smallest float number
transform = CGAffineTransformScale(transform, scalePercentage, scalePercentage);
}
else
{
transform = CGAffineTransformScale(transform, wScalePercentage, hScalePercentage);
}
return transform;
}

Resources