围绕其中心旋转 UIImageView

Rotate UIImageView around its center

我正在尝试旋转两个 UIImage 的中心,但我遇到了问题(您可以查看下面的 gif 图片),旋转没问题,但图像上下摆动,有人知道这是什么吗可以吗?

Loader Animation

Loader Animation with background color

这是我用来旋转图像的代码

extension UIView {

private static let kRotationAnimationKey = "rotationAnimationKey"

func rotate(_ reversed: Bool = false, _ duration: Double = 1) {
    if layer.animation(forKey: UIView.kRotationAnimationKey) == nil {
        let rotationAnimation = CABasicAnimation(keyPath: "transform.rotation")
        rotationAnimation.fromValue = 0.0
        rotationAnimation.toValue = reversed ? -(Float.pi * 2.0) : Float.pi * 2.0
        rotationAnimation.duration = duration
        rotationAnimation.repeatCount = Float.infinity
        layer.add(rotationAnimation, forKey: UIView.kRotationAnimationKey)
    }
}

func stopRotating() {
    if layer.animation(forKey: UIView.kRotationAnimationKey) != nil {
        layer.removeAnimation(forKey: UIView.kRotationAnimationKey)
    }
}

谢谢大家!

回答如下:

It looks like your image asset isn’t centred properly. Set the background colour of your image view so you can tell. The image view is probably rotating about its center, but the image content itself is probably off center. - Peter Parker

Basically your image of the rings does not have the rings smack in the middle. So you need to put that image into photoshop and export a new one such that the rings are smack in the middle. Peter Parker

谢谢Peter Parker

为此动画创建了一个圆形视图使用 ShapeLayer 和 UIBezierPath 你可以使用这个 class

public class CirclesView: UIView {

    //MARK:- properties
    private var numberOfCircles: Int = 2
    private var lineWidth: CGFloat = 8.0
    private var space = 20
    private var color : UIColor = .white
    private static let kRotationAnimationKey = "rotationanimationkey"

    private lazy var circularLayer: CAShapeLayer = {
        let shapeLayer = CAShapeLayer()
        shapeLayer.fillColor = UIColor.clear.cgColor
        shapeLayer.strokeColor = color.cgColor
        shapeLayer.lineCap = .round
        shapeLayer.lineWidth = self.lineWidth

        return shapeLayer
    }()

    //MARK:- inializer

    public init(_ circles: Int, circleWidth: CGFloat) {
        self.numberOfCircles = circles
        self.lineWidth = circleWidth
        super.init(frame: .zero)
        addSubLayer()
    }

    override init(frame: CGRect) {

        super.init(frame: frame)
        addSubLayer()
    }

    required init?(coder: NSCoder) {

        super.init(coder: coder)
        addSubLayer()
    }

    override public func layoutSubviews() {

        super.layoutSubviews()
        addCircles()

    }


}
private extension CirclesView {

    func addCircles() {
        circularLayer.bounds = self.bounds
        let bezierPath = UIBezierPath()

        let center = CGPoint(x: bounds.maxX / 2, y: bounds.maxY / 2)
        let maximumRadius =  min(bounds.maxX,bounds.maxY)/2 - (lineWidth / 2.0)
        var startAngle = CGFloat(60)
        var endAngle = CGFloat(130)


        for i in 1...numberOfCircles {

            let radius = maximumRadius - CGFloat(i * space)
            let  startX = center.x  + (radius) * CGFloat(cos(startAngle.deg2rad()))
            let  startY = center.y  + (radius) * CGFloat(sin(startAngle.deg2rad()))

            bezierPath.move(to: CGPoint(x: startX,y: startY))
            bezierPath.addArc(withCenter: center, radius: radius, startAngle: startAngle.deg2rad(), endAngle: endAngle.deg2rad(), clockwise: false)

            startAngle = startAngle - 10
            endAngle = endAngle + 50

        }

        circularLayer.path = bezierPath.cgPath
    }

    func addSubLayer() {
        self.backgroundColor = .clear
        layer.addSublayer(circularLayer)

    }


}

 //MARK:- Public Functions
public extension CirclesView {

    func startAnimation(_ reversed: Bool = false, _ duration: Double = 1) {

        let rotateAnimation = CABasicAnimation(keyPath: "transform.rotation")
        rotateAnimation.fromValue = 0.0
        rotateAnimation.toValue = reversed ? -(Float.pi * 2.0) : Float.pi * 2.0
        rotateAnimation.duration = duration
        rotateAnimation.repeatCount = Float.infinity
        self.circularLayer.add(rotateAnimation, forKey: Self.kRotationAnimationKey)
    }

    func stopAnimation() {
        if let _ = circularLayer.animation(forKey: Self.kRotationAnimationKey)  {

            let rotateAnimation = CABasicAnimation(keyPath: "transform.rotation")
            rotateAnimation.fromValue = circularLayer.presentation()?.value(forKeyPath: "transform.rotation")
            rotateAnimation.toValue = 0
            rotateAnimation.duration = 0.5
            rotateAnimation.repeatCount = 0
            rotateAnimation.isRemovedOnCompletion = true
            self.circularLayer.removeAnimation(forKey: Self.kRotationAnimationKey)
            self.circularLayer.add(rotateAnimation, forKey: Self.kRotationAnimationKey)
        }
    }

    func pauseLayer(){
        let pausedTime : CFTimeInterval = layer.convertTime(CACurrentMediaTime(), from: nil)
        circularLayer.speed = 0.0
        circularLayer.timeOffset = pausedTime
    }
}


 extension CGFloat {
    func deg2rad() -> CGFloat {
        return self * .pi / 180
    }
}

Github Project Link