CAShapelayer 如何通过动画从圆形转换为方形(反之亦然)?

How CAShapelayer transform from circle to square (or vice versa) with animation?

CAShapelayer 如何使用 CABasicAnimation 从圆形变为方形(反之亦然)?

你可以玩 cornerRadius。例如,

   UIView *testView = [[UIView alloc]initWithFrame:CGRectMake(50, 50, 50, 50)];

CAShapeLayer *layer = [[CAShapeLayer alloc]initWithLayer:testView.layer];  // this is square layer

layer.cornerRadius = 25.0; // this is round layer

layer.cornerRadius = 0.0; // this is again square layer

您可以像上面的方法一样直接将视图从圆形切换到方形,从方形切换到圆形!

这里是创建圆的路径:

- (UIBezierPath *)circlePathWithCenter:(CGPoint)center radius:(CGFloat)radius
{    
UIBezierPath *circlePath = [UIBezierPath bezierPath];
[circlePath addArcWithCenter:center radius:radius startAngle:0 endAngle:M_PI/2 clockwise:YES];
[circlePath addArcWithCenter:center radius:radius startAngle:M_PI/2 endAngle:M_PI clockwise:YES];
[circlePath addArcWithCenter:center radius:radius startAngle:M_PI endAngle:3*M_PI/2 clockwise:YES];
[circlePath addArcWithCenter:center radius:radius startAngle:3*M_PI/2 endAngle:M_PI clockwise:YES];
[circlePath closePath];
return circlePath;
}

这是方形路径:

- (UIBezierPath *)squarePathWithCenter:(CGPoint)center size:(CGFloat)size
{
CGFloat startX = center.x-size/2;
CGFloat startY = center.y-size/2;

UIBezierPath *squarePath = [UIBezierPath bezierPath];
[squarePath moveToPoint:CGPointMake(startX, startY)];
[squarePath addLineToPoint:CGPointMake(startX+size, startY)];
[squarePath addLineToPoint:CGPointMake(startX+size, startY+size)];
[squarePath addLineToPoint:CGPointMake(startX, startY+size)];
[squarePath closePath];
return squarePath;
}

动画部分

CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"path"];
animation.duration = 1;
animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];

animation.fromValue = (__bridge id)(self.stateLayer.path);
    animation.toValue = (__bridge id)(self.stopPath.CGPath);
self.stateLayer.path = self.stopPath.CGPath;

[self.stateLayer addAnimation:animation forKey:@"animatePath"];

在做了一些变通之后,我就这样结束了

首先为方形和圆形路径以及 CAShapeLayer 对象制作 UIBezierPath 的全局对象。

@implementation Demo{
        CAShapeLayer *shapeLayer;
        UIBezierPath *sqPath;
        UIBezierPath *crclePath;
    }

现在,自定义您的 shapeLayer 并添加到下面 viewDidLoad 中的图层。

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    shapeLayer = [CAShapeLayer layer];
    shapeLayer.strokeColor = [[UIColor redColor] CGColor];
    shapeLayer.lineWidth = 2;
    shapeLayer.lineJoin = kCALineCapRound;
    sqPath = [self makeSquare:self.view.center squareWidth:200];
    shapeLayer.path = [sqPath CGPath];
    crclePath = [self makeCircle:self.view.center radius:100];
    [self.view.layer addSublayer:shapeLayer];
}

下面是制作完美正方形的方法

-(UIBezierPath*)makeSquare:(CGPoint)centrePoint squareWidth:(float)gain{
    float x=centrePoint.x-(gain/2);
    float y=centrePoint.y-(gain/2);
    UIBezierPath *apath = [UIBezierPath bezierPath];
    [apath moveToPoint:CGPointMake(x,y)];
    [apath addLineToPoint:apath.currentPoint];
    [apath addLineToPoint:CGPointMake(x+gain,y)];
    [apath addLineToPoint:apath.currentPoint];
    [apath addLineToPoint:CGPointMake(x+gain,y+gain)];
    [apath addLineToPoint:apath.currentPoint];
    [apath addLineToPoint:CGPointMake(x,y+gain)];
    [apath addLineToPoint:apath.currentPoint];
    [apath closePath];
    return apath;
}

下面是制作圆圈的方法

- (UIBezierPath *)makeCircle:(CGPoint)center radius:(CGFloat)radius
{
    UIBezierPath *circlePath = [UIBezierPath bezierPath];
    [circlePath addArcWithCenter:center radius:radius startAngle:-M_PI endAngle:-M_PI/2 clockwise:YES];
    [circlePath addArcWithCenter:center radius:radius startAngle:-M_PI/2 endAngle:0 clockwise:YES];
    [circlePath addArcWithCenter:center radius:radius startAngle:0 endAngle:M_PI/2 clockwise:YES];
    [circlePath addArcWithCenter:center radius:radius startAngle:M_PI/2 endAngle:M_PI clockwise:YES];
    [circlePath addArcWithCenter:center radius:radius startAngle:M_PI endAngle:-M_PI clockwise:YES];
    [circlePath closePath];
    return circlePath;
}

最后,在 btnDone 的动作中完成动画,它使用 CABasicAnimation 动画从方形到圆形的转换,反之亦然。

- (IBAction)btnDone:(id)sender {
    btnDowrk.selected=!btnDowrk.selected;
    CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"path"];
    animation.duration = 1;
    animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
    if (btnDowrk.selected) {
        animation.fromValue = (__bridge id)(sqPath.CGPath);
        animation.toValue = (__bridge id)(crclePath.CGPath);
        shapeLayer.path = crclePath.CGPath;
    }
    else{
        animation.fromValue = (__bridge id)(crclePath.CGPath);
        animation.toValue = (__bridge id)(sqPath.CGPath);
        shapeLayer.path = sqPath.CGPath;
    }
    [shapeLayer addAnimation:animation forKey:@"animatePath"];
}