复杂路径的动画,我们可以借助关键关键帧动画(CAKeyframeAnimation)来实现,给其的path属性设置相应的路径信息即可。
以下为一个红色的小球按照指定的路径运动的动画。
此动画关键在于如何把路径画出来(如两个圆弧)
//创建一个可变路径 let circleKeyframePath = CGPathCreateMutable() //创建用于转移坐标的Transform,这样我们不用按照实际显示做坐标计算,以这个坐标做基准点。坐标为下半个弧的中心点 var circleKeyframeTransform:CGAffineTransform = CGAffineTransformMakeTranslation(self.view.frame.size.width / 2, 260) CGPathMoveToPoint(circleKeyframePath, &circleKeyframeTransform, 0, 0) //CGPathAddLineToPoint(circleKeyframePath, &circleKeyframeTransform, -100, 0) //创建一个1/4弧(圆的左下角弧) CGPathAddArc(circleKeyframePath, &circleKeyframeTransform, 0, -100, 100, CGFloat(0.5 * M_PI), CGFloat(M_PI), false) CGPathAddLineToPoint(circleKeyframePath, &circleKeyframeTransform, -100, -100) CGPathAddLineToPoint(circleKeyframePath, &circleKeyframeTransform, -50, -100) //创建一个以半径为50的两条切线的内切圆弧 CGPathAddArcToPoint(circleKeyframePath, &circleKeyframeTransform, 0, -200, 50, -100, 50) CGPathAddLineToPoint(circleKeyframePath, &circleKeyframeTransform, 50, -100) CGPathAddLineToPoint(circleKeyframePath, &circleKeyframeTransform, 100, -100) //CGPathAddLineToPoint(circleKeyframePath, &circleKeyframeTransform, 100, 0) //创建一个1/4弧(圆的右下角弧) CGPathAddArc(circleKeyframePath, &circleKeyframeTransform, 0, -100, 100, 0, CGFloat(0.5 * M_PI), false) //关闭路径 CGPathCloseSubpath(circleKeyframePath) let backgroundLayer:CAShapeLayer = CAShapeLayer() backgroundLayer.path = circleKeyframePath backgroundLayer.strokeColor = UIColor.yellowColor().CGColor backgroundLayer.lineWidth = 3 backgroundLayer.fillColor = UIColor.clearColor().CGColor self.view.layer.addSublayer(backgroundLayer)
此时在模拟器上运行后的效果如下:
看起来还不错哦。像个元宝,呵,接下来就创建一个UIView对象让它成圆形,并按此路径做运动即可。
let circleView:UIView = UIView(frame: CGRect(x: 0, y: 0, 20, height: 20)) let redCircleLayer:CAShapeLayer = CAShapeLayer() let redCirclePath:UIBezierPath = UIBezierPath(ovalInRect: CGRect(x: 0, y: 0, 20, height: 20)) redCircleLayer.path = redCirclePath.CGPath redCircleLayer.fillColor = UIColor.redColor().CGColor circleView.layer.addSublayer(redCircleLayer) self.view.addSubview(circleView) //创建关键帧动画对象 let circleKeyframeAnimation:CAKeyframeAnimation = CAKeyframeAnimation(keyPath: "position") circleKeyframeAnimation.path = circleKeyframePath circleKeyframeAnimation.duration = 5 //让 Core Animation 向被驱动的对象施加一个恒定速度,不管路径的各个线段有多长。 circleKeyframeAnimation.calculationMode = kCAAnimationPaced circleKeyframeAnimation.repeatCount = HUGE //让它自身也做旋转,不过是圆的看不出效果 circleKeyframeAnimation.rotationMode = kCAAnimationRotateAutoReverse //print(circleView.layer.anchorPoint) circleView.layer.addAnimation(circleKeyframeAnimation, forKey: nil)
到此,就完成了,比较重要的要区分CGPathAddArc以及CGPathAddLineToPoint的不同,不同可以参考StackOverflow
CGPathAddArc方法工作方式类似于,(x,y)为圆心所在的坐标,radius为圆的半径,startAngle路径开始的角度按弧度算,endAngle路径结束的角度按弧度算,
clockwise方向(与实际的方向相反)
CGPathAddLineToPoint方法工作如下图,x1,y1,x2,y2为方法的四个位置参数,r为半径。