【问题标题】:Moving arc segment path along bigger arc path. SWIFT沿着更大的弧线路径移动弧线段路径。迅速
【发布时间】:2020-07-20 19:19:18
【问题描述】:

我正在尝试制作沿“母”弧线路径(红色部分)移动弧线段路径(绿色部分)的动画。

mainView

这里是完整的存储库:https://github.com/gmb55/movingArcs

完整代码:


import UIKit

class MovingArcs: UIView {
    var path: UIBezierPath!
    var shapeLayer: CAShapeLayer!
    var movement: CAKeyframeAnimation!

    // set path for moving and draw it on screen
    func pathShapeLayer() -> UIBezierPath {
        let startDegree = 180.0
        let endDegree = 360.0
        let start = CGFloat(startDegree).toRadians()
        let end = CGFloat(endDegree).toRadians()

        path = UIBezierPath(arcCenter: CGPoint(x: 100, y: 100),
            radius: 100.0,
            startAngle: start,
            endAngle: end,
            clockwise: true)

        let pathShapeLayer = CAShapeLayer()
        pathShapeLayer.path = path.cgPath
        pathShapeLayer.fillColor = UIColor.clear.cgColor
        pathShapeLayer.lineWidth = CGFloat(4)
        pathShapeLayer.strokeColor = UIColor.red.cgColor
        pathShapeLayer.position = .init(x: 0, y: 0)

        self.layer.addSublayer(pathShapeLayer)

        return path
    }

    // set movemnet along path with rotation
    func addAnimation() {
        let movement = CAKeyframeAnimation(keyPath: "position")
        movement.path = pathShapeLayer().cgPath
        movement.duration = 3
        movement.repeatCount = 1
        movement.rotationMode = CAAnimationRotationMode.rotateAuto
        movement.calculationMode = CAAnimationCalculationMode.paced
        movement.timingFunctions = [CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeOut)]
        self.movement = movement
    }

    // set path for arc that will be moving
    func movingArc() -> UIBezierPath {
        let startDegree = 180.0
        let endDegree = 210.0
        let start = CGFloat(startDegree).toRadians()
        let end = CGFloat(endDegree).toRadians()

        let arcPath = UIBezierPath(arcCenter: CGPoint(x: 100, y: 100),
            radius: 100.0,
            startAngle: start,
            endAngle: end,
            clockwise: true)

        return arcPath
    }

    // draw shapeLayer for moving arc
    func movingArcLayer() -> CAShapeLayer {
        let color = UIColor.green

        let backgroundCircleLayer = CAShapeLayer()
        backgroundCircleLayer.path = movingArc().cgPath
        backgroundCircleLayer.fillColor = UIColor.clear.cgColor
        backgroundCircleLayer.strokeColor = color.cgColor
        backgroundCircleLayer.lineWidth = 4.0
        backgroundCircleLayer.anchorPoint = CGPoint(x: 0.5, y: 0.5)
      //  backgroundCircleLayer.position = CGPoint(x: 0, y: 100)
      //  backgroundCircleLayer.transform = CATransform3DMakeTranslation(0, -100, 0)
      //  backgroundCircleLayer.transform = CATransform3DMakeRotation(CGFloat(-180).toRadians(), 0, 0, 1)

        self.layer.addSublayer(backgroundCircleLayer)

        return backgroundCircleLayer
    }

    // init for animation
    func initiateAnimation() {
        let layer = movingArcLayer()
        layer.add(self.movement, forKey: "Object Movement")
    }

    init() {
        super.init(frame: .zero)
        addAnimation()
        movingArcLayer()
        initiateAnimation()
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }
}

extension CGFloat {
    func toRadians() -> CGFloat {
        return self * CGFloat(Double.pi) / 180.0
    }
}

当绿色弧码看起来像这样时,它正在移动但在错误的位置,而不是沿着红色路径。 https://media.giphy.com/media/loSPpw2TPNNJyXSqcO/giphy.gif

当我将变换设置为:

  backgroundCircleLayer.position = CGPoint(x: 0, y: 100)
  backgroundCircleLayer.transform = CATransform3DMakeTranslation(0, -100, 0)

它在正确的路径上移动,但旋转错误: https://media.giphy.com/media/S85AIcXObCMfOhAjEe/giphy.gif

当我将变换设置为:

 backgroundCircleLayer.position = CGPoint(x: 100, y: 0)
 backgroundCircleLayer.transform = CATransform3DMakeTranslation(-100, 0, 0)

它在错误的路径上移动(90 度偏移),但旋转是正确的。 https://media.giphy.com/media/mEEWv5i32TELTseyQG/giphy.gif

问题是,我应该如何正确设置图层变换,也许你知道解释 CoreAnimation 工作原理的好教程?

【问题讨论】:

    标签: swift path core-animation automatic-ref-counting


    【解决方案1】:

    问题在于我如何声明绿色弧线的路径。以前它是一条粗曲线。但现在是二维平面。

    下面的工作代码:

    import UIKit
    
    class MovingRect: UIView {
        var path: UIBezierPath!
        var shapeLayer: CAShapeLayer!
        var movement: CAKeyframeAnimation!
    
        // set path for moving and draw it on screen
        func pathShapeLayer() -> UIBezierPath {
            let startDegree = 180.0
            let endDegree = 360.0
            let start = CGFloat(startDegree).toRadians()
            let end = CGFloat(endDegree).toRadians()
    
            path = UIBezierPath(arcCenter: CGPoint(x: 100, y: 100),
                radius: 100.0,
                startAngle: start,
                endAngle: end,
                clockwise: true)
    
            let pathShapeLayer = CAShapeLayer()
            pathShapeLayer.path = path.cgPath
            pathShapeLayer.fillColor = UIColor.clear.cgColor
            pathShapeLayer.lineWidth = CGFloat(4)
            pathShapeLayer.strokeColor = UIColor.red.cgColor
            pathShapeLayer.position = .init(x: 0, y: 0)
    
            self.layer.addSublayer(pathShapeLayer)
    
            return path
        }
    
        // set movemnet along path with rotation
        func addAnimation() {
            let movement = CAKeyframeAnimation(keyPath: "position")
            movement.path = pathShapeLayer().cgPath
            movement.duration = 2
            movement.repeatCount = 1
            movement.rotationMode = CAAnimationRotationMode.rotateAuto
            movement.calculationMode = CAAnimationCalculationMode.paced
            movement.timingFunctions = [CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeOut)]
            self.movement = movement
        }
        
        func movingArcPath() -> UIBezierPath {
            let startDegree = 255.0
            let endDegree = 285.0
            let start = CGFloat(startDegree).toRadians()
            let end = CGFloat(endDegree).toRadians()
    
            path = UIBezierPath()
          
            path.addArc(withCenter: CGPoint(x: 100, y: 100), radius: 110, startAngle: start, endAngle: end, clockwise: true)
            path.addArc(withCenter: CGPoint(x: 100, y: 100), radius: 90, startAngle: end, endAngle: start, clockwise: false)
            path.close()
            
            return path
        }
        
        // draw shapeLayer for moving arc
        func movingArcLayer() -> CAShapeLayer {
            let color = UIColor.green
    
            let movingRectLayer = CAShapeLayer()
            movingRectLayer.path = movingArcPath().cgPath
            movingRectLayer.fillColor = color.cgColor
            movingRectLayer.strokeColor = color.cgColor
            movingRectLayer.lineWidth = 4.0
            movingRectLayer.transform = CATransform3DMakeTranslation(-100, 0, 0)
            movingRectLayer.position = CGPoint(x: 200, y: 100)
            movingRectLayer.anchorPoint = CGPoint(x: 200, y: 100)
         //   movingRectLayer.transform = CATransform3DMakeRotation(CGFloat(90).toRadians(), 0, 0, 1)
        
            self.layer.addSublayer(movingRectLayer)
    
            return movingRectLayer
        }
    
        // init for animation
        func initiateAnimation() {
            let layer = movingArcLayer()
            layer.add(self.movement, forKey: "Object Movement")
        }
    
        init() {
            super.init(frame: .zero)
            addAnimation()
            initiateAnimation()
          //  removeArcLayer()
            
        }
    
        required init?(coder aDecoder: NSCoder) {
            super.init(coder: aDecoder)
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-02-17
      • 1970-01-01
      • 2016-08-25
      • 1970-01-01
      • 1970-01-01
      • 2018-09-20
      • 2021-02-27
      相关资源
      最近更新 更多