swift 围绕另一个视图的中心点旋转360度的动画

vuktfyat  于 2022-11-21  发布在  Swift
关注(0)|答案(1)|浏览(351)

我制作了一个加载旋转动画,它将视图从中间向外推,然后围绕中心视图旋转回到它的原始位置。这就是我试图实现的:

内部箭头将视图从中心移开。我已经做到了这一点,我所坚持的部分是围绕中心视图旋转视图。我读过许多其他的StackOverflow帖子,但还没有接近实现这一点。
目前代码:

UIView.animate(withDuration: 0.5) {

            self.topView.transform = CGAffineTransform(translationX: 20, y: -20)

        } completion: { _ in
            
            self.topView.setAnchorPoint(self.centerView.center)
                
            // Rotate
            
        }
}

下面是我如何设置视图的锚点。我使用这个方法是因为在设置锚点时视图会消失。

func setAnchorPoint(_ point: CGPoint) {
            var newPoint = CGPoint(x: bounds.size.width * point.x, y: bounds.size.height * point.y)
            var oldPoint = CGPoint(x: bounds.size.width * layer.anchorPoint.x, y: bounds.size.height * layer.anchorPoint.y);

            newPoint = newPoint.applying(transform)
            oldPoint = oldPoint.applying(transform)

            var position = layer.position

            position.x -= oldPoint.x
            position.x += newPoint.x

            position.y -= oldPoint.y
            position.y += newPoint.y

            layer.position = position
            layer.anchorPoint = point
}

一旦完整的360旋转完成,我需要将视图移回中心,完成动画。

lfapxunr

lfapxunr1#

对于加载视图围绕圆形视图旋转的部分,可以使用UIBezierPath,并根据其路径创建一个CAKeyframeAnimation,看看这个实现,希望能有所帮助。

class LoadingViewController: UIViewController {

    var circlePath: UIBezierPath!
    lazy var loader = makeLoader()
    lazy var centerView = makeCenterView()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        setup()
    }
    
    func makeLoader() -> UIButton {
        let padding: CGFloat = 100
        let width = self.view.frame.width - (2 * padding)
        let b = UIButton(frame: CGRect(x: padding, y: 200, width: width, height: 50))
        b.addTarget(self, action: #selector(didTap), for: .touchUpInside)
        b.backgroundColor = .blue
        return b
    }
    
    func makeCenterView() -> UIView {
        let width: CGFloat = 20
        let height: CGFloat = 20
        let x = self.view.center.x - width/2
        let y = self.view.center.y - height/2
        
        let view = UIView(frame: CGRect(x: x, y: y, width: width, height: height))
        view.backgroundColor = .green
        return view
    }

    func setup() {
        //create a UIBezierPath with a center that is at the center of the green view and a radius that has a length as the distance between the green view and the blue view.
        let arcCenterX = centerView.center.x
        let arcCenterY = centerView.center.y
        let arcCenter = CGPoint(x: arcCenterX, y: arcCenterY)
        let radius = arcCenterY - loader.center.y
        let startAngle = -CGFloat.pi/2
        let endAngle = CGFloat.pi*(1.5)
        
        let arcPath = UIBezierPath(arcCenter: arcCenter, radius:  radius, startAngle: startAngle, endAngle: endAngle, clockwise: true)
        self.circlePath = arcPath
        
        self.view.addSubview(loader)
        self.view.addSubview(centerView)
    }
    
    @objc func didTap() {
        //create a CAKeyframeAnimation with a path that matches the UIBezierPath above.
        let loadAnimation = CAKeyframeAnimation(keyPath: "position")
        loadAnimation.path = self.circlePath.cgPath
        loadAnimation.calculationMode = .paced
        loadAnimation.duration = 2.0
        loadAnimation.rotationMode = .rotateAuto
        
        loadAnimation.repeatCount = Float(CGFloat.greatestFiniteMagnitude)
        loader.layer.add(loadAnimation, forKey: "circleAnimation")
    }

}

相关问题