围绕其中心旋转 UIImageView

Posted

技术标签:

【中文标题】围绕其中心旋转 UIImageView【英文标题】:Rotate UIImageView around its center 【发布时间】:2020-05-09 15:42:08 【问题描述】:

我正在尝试将两个 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)
    

谢谢大家!

【问题讨论】:

您的图片资源似乎没有正确居中。设置图像视图的背景颜色,以便您知道。图像视图可能围绕其中心旋转,但图像内容本身可能偏离中心。 @PeterParker 我相信是这样,我更新了帖子并添加了带有背景的图像 gif。你知道如何让图片内容居中吗? 你必须在 Photoshop 中完成。 基本上你的戒指图片中间没有戒指。因此,您需要将该图像放入 Photoshop 并导出一个新图像,以使圆环位于中间。 @PeterParker 谢谢 【参考方案1】:

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

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

【讨论】:

谢谢@jawadAli 我会先尝试使用图片,因为我的客户可能会更改一些内容,但如果我将来需要,我已经下载了你的项目【参考方案2】:

回答如下:

您的图片资源似乎没有正确居中。设置图像视图的背景颜色,以便您知道。图像视图可能围绕其中心旋转,但图像内容本身可能偏离中心。 - Peter Parker

基本上,您对戒指的印象中没有戒指在中间。因此,您需要将该图像放入 Photoshop 并导出一个新图像,以使圆环位于中间。 Peter Parker

谢谢Peter Parker

【讨论】:

以上是关于围绕其中心旋转 UIImageView的主要内容,如果未能解决你的问题,请参考以下文章

当围绕其中心旋转图像时,为啥需要添加/减去质心?

如何计算围绕其中心旋转的矩形的边界框?

围绕其中心旋转 GLUT 位图/笔划字符串?

围绕其中心旋转图像

围绕其中心旋转可缩放和翻译的 SVG 元素

Pygame,围绕中心旋转使图像消失