How to animate PieChart sector on highlight for the Charts library? - ios-charts

When I highlight a sector in a PieChartView, the sector changes to the dataSet's highlightColor + the selectionShift. However this happens immediately and I'd like to animate this transition.
Currently the only animate function I see is for ChartViewBase, which animates the entire chart (which is what I do not want).
Is there anyway to only animate a single (selected) sector?
I have the following code as a starting point, but I can't apply transform to the entry nor the highlight
func chartValueSelected(_ chartView: ChartViewBase, entry: ChartDataEntry, highlight: Highlight) {
let translation1 = CGAffineTransform(scaleX: 1.5, y: 1.5)
let translation2 = CGAffineTransform(translationX: 1.0, y: 1.0)
UIView.animate(withDuration: 0.4, animations: { in
entry.transform = translation1
}) { didComplete in
UIView.animate(withDuration: 0.4, animations: {
entry.transform = translation2
})
}
}

have you tried below property for animation selected value ?
self.pieChart.highlightPerTapEnabled = true
Check this may be help to animate while highlighted.

Related

Mimic spring used in UIKit animation with SwiftUI

I'm struggling to figure out how to get SwiftUI's .spring animation to mimic what I'd previously done in UIKit. The UIKit code below animates an ImageView to make it pulse, almost like it's springing when punched, when tapped (.gif below shows this in action, imageView is the name of the imageView being animated).
This code immediately shrinks the image by 20 points at each corner (40 pts total), then transitions back to the original size over 0.25 seconds with some spring dampening.
#IBAction func imageTapped(_ sender: UITapGestureRecognizer) {
let originalImageFrame = imageView.frame
let imageWidthShrink: CGFloat = 20
let imageHeightShrink: CGFloat = 20
let smallerImageFrame = CGRect(
x: imageView.frame.origin.x + imageWidthShrink,
y: imageView.frame.origin.y + imageHeightShrink,
width: imageView.frame.width - (imageWidthShrink * 2),
height: imageView.frame.height - (imageHeightShrink * 2))
imageView.frame = smallerImageFrame
playSound(name: "punchSound")
UIView.animate(withDuration: 0.25, delay: 0.0, usingSpringWithDamping: 0.2, initialSpringVelocity: 10.0, options: [], animations: {
self.imageView.frame = originalImageFrame
})
}
In SwiftUI I can trigger an .animation, putting a .spring inside, triggering this when I tap the image, but it sort of mimics the pulsing but switches between 1.0 and 1.1 scale size. What I want to do is immediately scale to the shorter size, then bounce out to the original size with a spring animation over a time period. Thanks to any sharing insights.
#State private var animateImage = false
...
selectedImage
.resizable()
.scaledToFit()
.scaleEffect(animateImage ? 1.0 : 1.1)
.animation(.spring(response: 0.3, dampingFraction: 0.3), value: animateImage)
.onTapGesture {
print("You tapped me!")
playSound(name: "punchSound")
animateImage.toggle()
}
You can use explicit animation in the tap Gesture to first immediately "shrink" to 0.9 without animation and then expand back WITH animation:
Image("clown")
.resizable()
.scaledToFit()
.scaleEffect(animateImage ? 0.9 : 1.0)
.onTapGesture {
animateImage.toggle()
withAnimation(.spring(response: 0.3, dampingFraction: 0.3)) {
animateImage.toggle()
}
}

UISlider will not move if two transform are made

I have a UISlider that was implemented through Storyboard. I added a Keypath layer.transform.rotation.z with a value of 1.57 in order to make the UISlider vertical.
I also have a MoveRight UIButton that controls 3 elements (Two UIImageViews and One UISlider) to move in unison. The code for the transform is shown below
#IBAction func MoveRight(_ sender: Any) {
// Used to Show Reset Button for Right
ResetOrigin.isHidden = false
let yPosition1 = myslider.frame.origin.y
let yPosition2 = ImageView.frame.origin.y
let yPosition3 = ImageView2.frame.origin.y
UIView.animate(withDuration: 0.0, delay: 0.0, options: [], animations: {
self.myslider.transform = CGAffineTransform(translationX: 0.001, y: yPosition1)
self.ImageView.transform = CGAffineTransform(translationX: 0.001, y: yPosition2)
self.ImageView2.transform = CGAffineTransform(translationX: 0.001, y: yPosition3)
}, completion: nil)
}
When the code is like this the movement works great although the UISlider is no longer Vertical after the transform. And when I try to add this line of code to the animation
self.myslider.transform = CGAffineTransform(rotationAngle: (CGFloat.pi / 2))
The slider will no longer move while the other 2 Elements are affected by the transform. I tried doing a separate .animate to see if that would resolve the problem but the same result is given. Any ideas on how to solve this issue would be greatly appreciated

Swift color change shows different color

I am trying to do a scale animation on an image view. Upon completion I am changing the image to a red colored version of it. But in between it shows a weird blue color which I dont want to show. This is the code I am using for the animation. Thanks
self.likeAnimateView.image = self.likeAnimateView.image!.withRenderingMode(UIImageRenderingMode.alwaysTemplate)
UIView.animate(withDuration: 0.182,
animations: {
self.likeAnimateView.transform = CGAffineTransform(scaleX: 0.5, y: 0.5)
},
completion: { _ in
UIView.animate(withDuration: 0.182) {
self.likeAnimateView.transform = CGAffineTransform.identity
self.likeAnimateView.image = UIImage(named: "heartsel") // Red image
}
})
As per the suggestion of #Karthikeyan Bose. I added this line of code before the animation.
self.likeAnimateView.image = UIImage(named: "heart")//Deafault color before the animation to get rid of the blue color
UIView.animate(withDuration: 0.182,
animations: {
self.likeAnimateView.transform = CGAffineTransform(scaleX: 0.5, y: 0.5)
},
completion: { _ in
UIView.animate(withDuration: 0.182) {
self.likeAnimateView.transform = CGAffineTransform.identity
self.likeAnimateView.image = UIImage(named: "heartsel") // Red image
}
})

How to transform only the button edge of a view with animation

I am trying to achieve an effect that when I swipe up on a view, the buttom edge will move towards the top until it disappears (the views height will become smaller and smaller).
I want the top edge to stay in place and only the buttom edge to move. how can i adjust this code to achieve that?
UIView.animate(withDuration: 5.0, animations: { () in
self.topView.translatesAutoresizingMaskIntoConstraints = false
self.topView.transform = CGAffineTransform(scaleX: 1,y: 5)
})
self.topView.transform = CGAffineTransform.identity
First you should need the order of the method calls your code (not absolutly necessary, but looks better):
self.topView.transform = CGAffineTransform.identity
UIView.animate(withDuration: 5.0, animations: { () in
self.topView.translatesAutoresizingMaskIntoConstraints = false
self.topView.transform = CGAffineTransform(scaleX: 1,y: 5)
})
This scale transform will shrink the view to the center; if you want to keep the top position, you would add a translateBy(x:y:) transformation and add it to the scale transform, more or less like this:
UIView.animate(withDuration: 5.0, animations: { () in
self.topView.translatesAutoresizingMaskIntoConstraints = false
let scaleTransform = CGAffineTransform(scaleX: 1,y: 5)
let translateTransform = CGAffineTransform(translationX: 0,y: -100)
let combined = scaleTransform.concatenating(translateTransform)
self.topView.transform = combined
})
Or you could just animate the frame of the view, as described here:
Core Animation for UIView.frame

Animation to scale and move UIView (swift)

I have a UIView, placed in the middle of the screen. When the user presses a button, I want it to move up near top of the screen as it shrinks to about a fifth of its size.
I have tried this:
UIView.animateWithDuration(0.7) { () -> Void in
self.main.transform = CGAffineTransformMakeScale(0.2, 0.2)
self.main.transform = CGAffineTransformMakeTranslation(0, -250)
}
But for some reason, that only scales the view. I have also tried to put this in the animateWithDuration:
self.main.frame = CGRectMake(self.view.frame.width/2 - 10, 50, 50, 50)
How can I get both animations to work?
Joe's answer above does exactly as his GIF describes but it doesn't really answer your question since it translates then scales the view (as opposed to both translating and scaling at the same time). Your issue is that you're setting the view's transform in your animation block then immediately overwritting that value with another transform. To achieve both translation and scale at the same time, you'll want something like this:
#IBAction func animateButton(_ sender: UIButton) {
let originalTransform = self.main.transform
let scaledTransform = originalTransform.scaledBy(x: 0.2, y: 0.2)
let scaledAndTranslatedTransform = scaledTransform.translatedBy(x: 0.0, y: -250.0)
UIView.animate(withDuration: 0.7, animations: {
self.main.transform = scaledAndTranslatedTransform
})
}
You can achieve basic UIView animation in several ways in Swift. Below code is just a simple approach...
class ViewController: UIViewController {
#IBOutlet weak var animationButton: UIButton!
#IBOutlet weak var myView: UIView!
override func viewDidLoad() {
super.viewDidLoad()
// I added seperate colour to UIView when animation move from one animation block to another.So, You can get better understanding how the sequence of animation works.
self.myView.backgroundColor = .red
}
#IBAction func animateButton(_ sender: UIButton) {
UIView.animate(withDuration: 0.5, delay: 0.0, options: UIViewAnimationOptions.curveEaseIn, animations: {
//Frame Option 1:
self.myView.frame = CGRect(x: self.myView.frame.origin.x, y: 20, width: self.myView.frame.width, height: self.myView.frame.height)
//Frame Option 2:
//self.myView.center = CGPoint(x: self.view.frame.width / 2, y: self.view.frame.height / 4)
self.myView.backgroundColor = .blue
},completion: { finish in
UIView.animate(withDuration: 1, delay: 0.25,options: UIViewAnimationOptions.curveEaseOut,animations: {
self.myView.backgroundColor = .orange
self.myView.transform = CGAffineTransform(scaleX: 0.25, y: 0.25)
self.animationButton.isEnabled = false // If you want to restrict the button not to repeat animation..You can enable by setting into true
},completion: nil)})
}
}
Output: