【问题标题】:Swift 3 CGAffineTransform on CGRectCGRect 上的 Swift 3 CGAffineTransform
【发布时间】:2017-03-30 17:02:43
【问题描述】:

基本上,我的目标是围绕我的徽标进行类似原子的运动 https://media.giphy.com/media/9oHZQ2gEez8ti/giphy.gif

let rect = CGRect(origin: CGPoint(x: Logo.position.x - (Logo.frame.width/3.6), y: Logo.position.y - (Logo.frame.height/2) - kViewSize.height/32), size: CGSize(width: Logo.frame.width/2, height: Logo.frame.height + kViewSize.height/16))
let ellipse = CGPath(ellipseIn: rect, transform: nil)
YellowMagic.run(SKAction.repeatForever(SKAction.follow(ellipse, asOffset: false, orientToPath: false, duration: 1.5)))

通过上面的代码,我得到了中间的椭圆,精灵根据需要围绕路径运行。

问题是通过旋转路径得到另外两个椭圆。我认为旋转路径是不可能的,所以我尝试使用以下代码旋转矩形。

var rect2 = rect
rect2 = rect2.applying(CGAffineTransform(rotationAngle: CGFloat(M_PI/4)))
let ellipse2 = CGPath(ellipseIn: rect2, transform: nil)

上面的代码没有旋转矩形,实际上它使矩形变成了正方形。必须有一个我在这里缺少的更简单的解决方案。非常感谢任何帮助。谢谢!

【问题讨论】:

    标签: ios swift3 cgaffinetransform cgrect cgpath


    【解决方案1】:

    要实现的目标

    我的 Xcode 示例项目

    https://github.com/junaidios/Oval-path-Animation

    动画视图

    https://github.com/junaidios/Oval-path-Animation/blob/master/JSAnimation/animation/JSCircleAnimtionView.swift

    我的尝试

    添加中心圆

       let centerCirclePath = UIBezierPath(ovalIn: CGRect(x: 162, y: 188, width: 20, height: 20))
       colorCircleLayerCenter.setFill()
       centerCirclePath.fill()
    

    添加椭圆

        let bezierPath1 = UIBezierPath()
        bezierPath1.move(to: CGPoint(x: 145.5, y: 213.93))
        bezierPath1.addCurve(to: CGPoint(x: 84.68, y: 131.46), controlPoint1: CGPoint(x: 83.75, y: 163.11), controlPoint2: CGPoint(x: 79.26, y: 136.87))
        bezierPath1.addCurve(to: CGPoint(x: 193.5, y: 178.49), controlPoint1: CGPoint(x: 87.4, y: 128.75), controlPoint2: CGPoint(x: 130.21, y: 128.39))
        bezierPath1.addCurve(to: CGPoint(x: 258.01, y: 269.86), controlPoint1: CGPoint(x: 256.33, y: 228.23), controlPoint2: CGPoint(x: 262.32, y: 266.63))
        bezierPath1.addCurve(to: CGPoint(x: 145.5, y: 213.93), controlPoint1: CGPoint(x: 249.34, y: 276.35), controlPoint2: CGPoint(x: 207.25, y: 264.75))
        bezierPath1.close()
    
        let bezierPath2 = UIBezierPath()
        bezierPath2.move(to: CGPoint(x: 145.5, y: 184.8))
        bezierPath2.addCurve(to: CGPoint(x: 254.5, y: 131.5), controlPoint1: CGPoint(x: 195.5, y: 146.16), controlPoint2: CGPoint(x: 238.27, y: 131.5))
        bezierPath2.addCurve(to: CGPoint(x: 200.5, y: 217.47), controlPoint1: CGPoint(x: 262.64, y: 131.5), controlPoint2: CGPoint(x: 261.5, y: 159.92))
        bezierPath2.addCurve(to: CGPoint(x: 84.5, y: 272.49), controlPoint1: CGPoint(x: 139.94, y: 274.6), controlPoint2: CGPoint(x: 91.01, y: 272.49))
        bezierPath2.addCurve(to: CGPoint(x: 145.5, y: 184.8), controlPoint1: CGPoint(x: 71.42, y: 272.49), controlPoint2: CGPoint(x: 95.5, y: 223.44))
        bezierPath2.close()
    
        let bezierPath3 = UIBezierPath()
        bezierPath3.move(to: CGPoint(x: 143.5, y: 201.45))
        bezierPath3.addCurve(to: CGPoint(x: 172, y: 89.5), controlPoint1: CGPoint(x: 143.5, y: 154.31), controlPoint2: CGPoint(x: 155.77, y: 89.5))
        bezierPath3.addCurve(to: CGPoint(x: 200.5, y: 201.45), controlPoint1: CGPoint(x: 180.14, y: 89.5), controlPoint2: CGPoint(x: 200.5, y: 124.29))
        bezierPath3.addCurve(to: CGPoint(x: 172, y: 307.5), controlPoint1: CGPoint(x: 200.5, y: 278.04), controlPoint2: CGPoint(x: 178.51, y: 307.5))
        bezierPath3.addCurve(to: CGPoint(x: 143.5, y: 201.45), controlPoint1: CGPoint(x: 158.92, y: 307.5), controlPoint2: CGPoint(x: 143.5, y: 248.58))
        bezierPath3.close()
    
        let linLayer1 = CAShapeLayer()
        linLayer1.path = bezierPath1.cgPath;
        linLayer1.strokeColor = colorLine.cgColor
        linLayer1.fillColor = UIColor.clear.cgColor
    
        self.layer.addSublayer(linLayer1);
    
        let lineLayer2 = CAShapeLayer()
        lineLayer2.path = bezierPath2.cgPath;
        lineLayer2.strokeColor = colorLine.cgColor
        lineLayer2.fillColor = UIColor.clear.cgColor
    
        self.layer.addSublayer(lineLayer2);
    
        let lineLayer3 = CAShapeLayer()
        lineLayer3.path = bezierPath3.cgPath;
        lineLayer3.strokeColor = colorLine.cgColor
        lineLayer3.fillColor = UIColor.clear.cgColor
    
        self.layer.addSublayer(lineLayer3);
    

    在椭圆上添加移动圆

        let circleLayer1 = CAShapeLayer()
        circleLayer1.path = UIBezierPath(ovalIn: CGRect(x: -10, y: -10, width: 20, height: 20)).cgPath;
        circleLayer1.fillColor = colorCircleLayer1.cgColor
    
        let circleLayer2 = CAShapeLayer()
        circleLayer2.path = UIBezierPath(ovalIn: CGRect(x: -10, y: -10, width: 20, height: 20)).cgPath;
        circleLayer2.fillColor = colorCircleLayer2.cgColor
    
        let circleLayer3 = CAShapeLayer()
        circleLayer3.path = UIBezierPath(ovalIn: CGRect(x: -10, y: -10, width: 20, height: 20)).cgPath;
        circleLayer3.fillColor = colorCircleLayer3.cgColor
    
        self.layer.addSublayer(circleLayer1);
        self.layer.addSublayer(circleLayer2);
        self.layer.addSublayer(circleLayer3);
    

    对圆圈应用动画

        circleLayer1.add(self.addAnimation(ovalPath: bezierPath1), forKey: "1");
        circleLayer2.add(self.addAnimation(ovalPath: bezierPath2), forKey: "2");
        circleLayer3.add(self.addAnimation(ovalPath: bezierPath3), forKey: "3");
    

    动画功能

    func addAnimation(ovalPath : UIBezierPath) -> CAKeyframeAnimation {
    
        let animation = CAKeyframeAnimation()
    
        animation.keyPath = "position"
        animation.repeatCount = HUGE
        animation.timingFunction = CAMediaTimingFunction.init(name: kCAMediaTimingFunctionLinear);
        animation.fillMode = kCAFillModeForwards;
        animation.repeatCount = .infinity
        animation.beginTime = 0.0
        animation.duration = 2.5
        animation.calculationMode = kCAAnimationPaced
    
        animation.path = ovalPath.cgPath
    
        return animation;
    }
    

    最终输出

    【讨论】:

    • 这太棒了!我没用过CAKeyframeAnimation、CAShapeLayer。使用带有 UIBezierPath 的ovalIn 也是我不知道的。您是如何得出分数的。
    【解决方案2】:

    我修改了here找到的函数,生成了如下函数:

    func createPathRotatedAroundBoundingBoxCenter(path: CGPath, radians: CGFloat) -> CGPath {
        let bounds = path.boundingBox; // might want to use   CGPathGetPathBoundingBox
        let center = CGPoint(x: bounds.midX, y: bounds.midY)
        var transform = CGAffineTransform(translationX: 0, y: 0)
        transform = transform.translatedBy(x: center.x, y: center.y)
        transform = transform.rotated(by: radians)
        transform = transform.translatedBy(x: -center.x, y: -center.y)
        return path.copy(using: &transform)!
    }
    

    然后我修改了我的代码以获得所需的结果。

    let rect = CGRect(origin: CGPoint(x: Logo.position.x - (Logo.frame.width/3.6), y: Logo.position.y - (Logo.frame.height/2) - kViewSize.height/32), size: CGSize(width: Logo.frame.width/2, height: Logo.frame.height + kViewSize.height/16))
    let ellipse = CGPath(ellipseIn: rect, transform: nil)
    let ellipse2a = CGPath(ellipseIn: rect, transform: nil)
    let ellipse3a = CGPath(ellipseIn: rect, transform: nil)
    let ellipse2 = createPathRotatedAroundBoundingBoxCenter(path: ellipse2b, radians: CGFloat(M_PI/4.0))
    let ellipse3 = createPathRotatedAroundBoundingBoxCenter(path: ellipse3b, radians: CGFloat(-M_PI/4.0))
    YellowMagic.run(SKAction.repeatForever(SKAction.follow(ellipse, asOffset: false, orientToPath: false, duration: 1)))
    RedMagic.run(SKAction.repeatForever(SKAction.follow(ellipse2, asOffset: false, orientToPath: false, duration: 1)))
    GreenMagic.run(SKAction.repeatForever(SKAction.follow(ellipse3, asOffset: false, orientToPath: false, duration: 1)))
    

    【讨论】:

    • 这是我也尝试过的解决方案之一,但之后动画和点的位置将成为问题
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-19
    • 2016-11-15
    • 1970-01-01
    • 2017-12-25
    相关资源
    最近更新 更多