如何在IOS中创建像月球绕地球旋转和同时自转这样的CAAnimation效果



我知道在IOS中创建月亮绕地球旋转的效果很简单。假设月球是一个CALayer对象,只需将该对象的锚点更改为地球,它就会围绕地球旋转。但是,如何创造同时自转的月球呢?由于月球只能有一个锚点,我似乎再也无法让这个CALayer对象自行旋转了。你们觉得怎么样?谢谢

您可以通过沿贝塞尔路径设置"月亮"的动画,使其围绕一个点旋转,同时设置旋转变换的动画。这里有一个简单的例子,

@interface ViewController ()
@property (strong,nonatomic) UIButton *moon;
@property (strong,nonatomic) UIBezierPath *circlePath;
@end
@implementation ViewController
-(void)viewDidLoad {
    self.moon = [UIButton buttonWithType:UIButtonTypeInfoDark];
    [self.moon addTarget:self action:@selector(clickedCircleButton:) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:self.moon];
}
- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];
    CGRect circleRect = CGRectMake(60,100,200,200);
     self.circlePath = [UIBezierPath bezierPathWithOvalInRect:circleRect];
     self.moon.center = CGPointMake(circleRect.origin.x + circleRect.size.width, circleRect.origin.y + circleRect.size.height/2.0);
}
- (void)clickedCircleButton:(UIButton *)sender {
    CAKeyframeAnimation *orbit = [CAKeyframeAnimation animationWithKeyPath:@"position"];
    orbit.path = self.circlePath.CGPath;
    orbit.calculationMode = kCAAnimationPaced;
    orbit.duration = 4.0;
    orbit.repeatCount = CGFLOAT_MAX;
    [self.moon.layer addAnimation:orbit forKey:@"circleAnimation"];
    CABasicAnimation *fullRotation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
    fullRotation.fromValue = 0;
    fullRotation.byValue   = @(2.0*M_PI);
    fullRotation.duration = 4.0;
    fullRotation.repeatCount = CGFLOAT_MAX;
    [self.moon.layer addAnimation:fullRotation forKey:@"Rotate"];
}

这些特定的值将导致"月亮"像地球的月亮一样保持朝向中心的同一面。

使用两层。

  • 一种是从地球延伸到月球的无形"手臂"。它围绕其锚点(地球的中心)进行旋转变换。这导致月球在"手臂"的末端围绕地球旋转。

  • 另一个是月亮。它是"手臂"的一个子层,位于手臂的末端。如果希望它独立旋转,请围绕锚点旋转,该锚点是它自己的中心。

(然而,要注意,真正的月球并没有这样做。对于真正的月球来说,"手臂"就足够了,因为真正的月球绕地球公转是同步的,所以我们看到的总是月球的同一面。)

我自己也在寻找这种实现。我遵循了rdelmar的答案,并使用了这个快速版本:

class ViewController: UIViewController {
var circlePath: UIBezierPath!
var moon = UIButton(frame: CGRect(x: 10, y: 10, width: 50, height: 50))
override func viewDidLoad() {
    super.viewDidLoad()
    setup()
}
func setup() {
    let circleRect = CGRect(x: 60, y: 100, width: 200, height: 200)
    self.circlePath = UIBezierPath(ovalIn: circleRect)
    self.moon.center = CGPoint(x: circleRect.origin.x + circleRect.size.width, y: circleRect.origin.y + circleRect.size.height/2.0)
    self.moon.addTarget(self, action: #selector(didTap), for: .touchUpInside)
    moon.backgroundColor = .blue
    self.view.addSubview(moon)
}
@objc func didTap() {
    let orbit = CAKeyframeAnimation(keyPath: "position")
    orbit.path = self.circlePath.cgPath
    orbit.calculationMode = .paced
    orbit.duration = 4.0
    orbit.repeatCount = Float(CGFloat.greatestFiniteMagnitude)
    moon.layer.add(orbit, forKey: "circleAnimation")
    
    let fullRotation = CABasicAnimation(keyPath: "transform.rotation.z")
    fullRotation.fromValue = 0
    fullRotation.byValue = CGFloat.pi*2
    fullRotation.duration = 4
    fullRotation.repeatCount = Float(CGFloat.greatestFiniteMagnitude)
    moon.layer.add(orbit, forKey: "Rotate")
}

}

相关内容

  • 没有找到相关文章

最新更新