I want to animate zooming-in and out from image in Swift using CAAnimation while preserving the original width and height of the image (i.e. show smaller area in the image enlarged).
I tried to use the following animation and it did animate the change in scale properly, but also changed the width and height of my image accordingly:
let animation = CABasicAnimation(keyPath: "transform.scale")
animation.fromValue = 1.4
animation.toValue = 1.0
animation.duration = 2
self.imageView.layer.add(animation, forKey: "scaleAnimation")
One solution would be to put the image view in a container view with the container view's clipToBounds set to true. This way as the image view is scaled larger, it will be clipped by its container view and appear to remain the same size. Make sure the container view's frame matches the unzoomed size of the image view.
Related
I wanted a custom slider and the requirement was the height of minView should be 8 pt & maxView should be 4 pt, it's the visible corners should be rounded.
I gave the slider's min & max image as clear image of alpha as 0.0
For maxView, I created a UIView and gave it width equal to slider's width, and made it's corners rouneded.
For minView, I created a UIView and it's leading is equal to leading of slider and trailing should be equal to the center of the thumb.
Here is the logic for what I did.
func changeValue() {
let difference = slider.maximumValue - slider.minimumValue
let thumbWidth = CGFloat(44/2)
let scale = (slider.frame.size.width-thumbWidth)/CGFloat(difference)
let width = scale * CGFloat(slider.value)
minSlideWidth.constant = width
self.view.layoutIfNeeded()
}
But the minView's width doesn't increase and decrease it's width with the thumb's center. If you see the image it had already crossed the UIslider's thumb.
How about this approach ?
Configure properties of UISlide control.
setMinimumTrackImage with 8pt image.
setMaximumTrackImage with 4pt image.
The track images could be re-created by stretchable image in order to keep the rounded corners. You can find it in the section Defining a Stretchable Image section from UIImage reference. It is very useful for track image of slide bar.
I am building a custom UIView that you can rotate and resize. I can resize the UIView by dragging the corners of the UIView. I calculate how much I have dragged then change the frame of the UIView accordingly.
However, I am running into problems once I added a rotation gesture recognizer to the view. If I rotate or apply a transform to the view, I no longer know how to calculate drag distance and change the frame of the view. How could I calculate the width and height change between my new view and the original view when things are put at an added angle or if they have some other transform, like a translation transform?
I thought of possibilities to set the view's transform back to .identity, change the size of the view, then re-apply its transform, but I'm not sure how to actually go about implementing this.
After applying transform you can not use frame
You have two options
1) First Calculate everything using center of your view
2) As you know apply identity and change frame
for point 2 I have added example that might helpful to you
let transform = imageView.transform
imageView.transform = CGAffineTransform.identity
var rect: CGRect = imageView.frame
rect = // Change Rect here
imageView.frame = rect // Assign it
imageView.transform = transform // Apply Transform
I have a custom UIView that is able to be scaled and rotated based on the values of a UISlider. Scaling is working well, it's simply:
self.myView.transform = CGAffineTransformScale(CGAffineTransformIdentity, sx, sy);
My UIView has a 2px border:
self.layer.borderColor = [UIColor whiteColor].CGColor;
self.layer.borderWidth = 2.0f;
However when I scale the view larger the border also grows in size. How can I keep a consistent border that ignores the scale of the view?
When you change the view scaling...:
self.layer.borderWidth = 2.0f / scaleFactor;
It is the purpose of scaling and therefore its expected behaviour, that a 2px frame woudl be scaled up or down along with the remaining view.
You could have one view with the color of your frame and set a view ontop that is 4px/4px smaller and located at 2/2 which carries the remaining view just without the frame.
Then change the frame of the underlying (frame) view accordingly. Then scale the subview accordingly. Make sure it remains centered or still starts at (2/2).
I'm developing an animated column bar chart and i having some trouble.
The bars show up with an scale animation. At the beginning all columns have 1 point size and will scale till a predefined height.
The point is: I want to draw a gradient into the columns (They are subclasses of UIView) and want the scale animation to recalculate the gradient.
Until now, i have drawn the gradient, but when the column scale, the gradient does not scale with it.
As the view have 1 point height, the gradient is show as 1 color only.
Can someone give me a north to solve this issue?
Solved the problem!
i was using scale instead of changing the view's bounds..
Was
view.transform = CGAffineTransformMakeScale(1.0, scaleY.floatValue);
Must be
view.bounds = CGRectMake(view.bounds.origin.x, view.bounds.origin.y * scaleY.floatValue, view.bounds.size.width, view.bounds.size.height * scaleY.floatValue);
Where scaleY was calculated before and is a NSNumber that contains the Y scale factor.
It's not necessary to set
view.contentMode = UIViewContentModeRedraw;
Thank you DarkDusk for the help.
Try setting the contentMode:
myView.contentMode = UIViewContentModeRedraw;
This will force a redraw on every size change.
I have a round image that I want to "squish" vertically so that it looks more like a horizontal line, then expand it back to the original shape. I thought this would work by setting the layer's anchor point to the center and then animating the frame via UIViewAnimation with the height of the frame = 1.
[self.imageToSquish.layer setAnchorPoint:CGPointMake(0.5, 0.5)];
CGRect newFrame = CGRectMake(self.imageToSquish.frame.origin.x, self.imageToSquish.frame.origin.y, self.imageToSquish.frame.size.width, 1 );
[UIView animateWithDuration:3
animations:^{self.imageToSquish.frame = newFrame;}
completion:nil];
But the image shrinks toward the top instead of around the center.
You’re giving it a frame that has its origin—at the top left—in the same position as it started. You probably want to do something more like this, adding half the image’s height:
CGRect newFrame = CGRectMake(self.imageToSquish.frame.origin.x, self.imageToSquish.frame.origin.y + self.imageToSquish.frame.size.height / 2, self.imageToSquish.frame.size.width, 1);
Alternatively—and more efficiently—you could set the image view’s transform property to, say, CGAffineTransformMakeScale(1, 0.01) instead of messing with its frame. That’ll be centered on the middle of the image, and you can easily undo it by setting the transform to CGAffineTransformIdentity.