动画CAShapeLayers

时间:2013-09-19 05:31:08

标签: ios objective-c animation cabasicanimation cashapelayer

我很少CAShapeLayers正在完成圆圈(参考图片)。现在我想在单个触摸上为所有图层设置动画。就像:现在,绿色CAShapeLayer的中心设置为0度。如果您选择红色CAShapeLayer,则CAShapeLayer的中心点将设置为0度。如果您选择黄色CAShapeLayer,则其中心将在0度进行。记住所有图层都应根据所选图层进行动画处理。我不想使用UIView。变换。我只想使用CABasicAnimation,CAAnimationGroup或KeyFrame动画。我正在使用单击手势。

enter image description here

enter image description here

请帮助我。谢谢你。

enter image description here

1 个答案:

答案 0 :(得分:0)

这是一个有效的演示

的AppDelegate

inline static CGPoint CGRectGetCenter( CGRect r )
{
    return (CGPoint){ CGRectGetMidX( r ), CGRectGetMidY( r ) } ;
}

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    // Override point for customization after application launch.
    self.window.backgroundColor = [UIColor whiteColor];
    [self.window makeKeyAndVisible];

    CGFloat size = 300.0 ;
    for( int index =0; index < 10; ++index )
    {
        RingView * view = [[ RingView alloc ] initWithFrame:(CGRect){ .size = { size, size } } ] ;
        view.outerRadius = size * 0.5 ;
        view.innerRadius = view.outerRadius - 20.0 ;
        view.center = CGRectGetCenter( self.window.bounds ) ;
        [ self.window addSubview:view ] ;

        size -= 20.0 ;
    }

    return YES;
}


-(void)ringViewTapped:(RingView*)sender sliceIndex:(NSNumber*)sliceIndex
{
    [ UIView animateWithDuration:0.25 animations:^{
        sender.transform = CGAffineTransformMakeRotation( -[ sliceIndex doubleValue ] * M_PI_2 ) ;
    } ] ;
}

@end

RingView

@interface RingView : UIControl
@property ( nonatomic ) CGFloat innerRadius, outerRadius ;
@end
@implementation UIResponder (Send)

-(BOOL)sendMessage:(SEL)message withObject:(id)obj0 withObject:(id)obj1
{
    UIResponder * target = self ;
    do
    {
        if ( [ target respondsToSelector:message ] )
        {
            [ target performSelector:message withObject:obj0 withObject:obj1 ] ;
            return YES ;
        }
        target = [ target nextResponder ] ;
    } while( target ) ;

    return NO ;
}

@end

@implementation UIColor (RandomColor)
+(UIColor*)randomColor
{
    return [ UIColor colorWithHue:((CGFloat)arc4random_uniform( 6 ) / 6.0) saturation:1.0 brightness:1.0 alpha:1.0 ] ;
}
@end

static CGPathRef CGPathCreateWedge( CGFloat innerRadius, CGFloat outerRadius )
{
    CGMutablePathRef p = CGPathCreateMutable() ;
    CGPathMoveToPoint( p, NULL, 0, innerRadius ) ;
    CGPathAddLineToPoint( p, NULL, 0, outerRadius ) ;
    CGPathAddArcToPoint( p, NULL, outerRadius, outerRadius, outerRadius, 0.0, outerRadius ) ;
    CGPathAddLineToPoint( p, NULL, innerRadius, 0.0 ) ;
    CGPathAddArcToPoint( p, NULL, innerRadius, innerRadius, 0.0, innerRadius, innerRadius ) ;
    CGPathCloseSubpath( p ) ;

    return p ;
}

@interface RingView ()
@end

@implementation RingView

-(void)_ensureSlices
{
    if ( self.layer.sublayers.count == 0 )
    {
        CGPathRef p = CGPathCreateWedge( self.innerRadius, self.outerRadius ) ;

        for( int index=0; index < 4; ++index )
        {
            CAShapeLayer * layer = [ CAShapeLayer layer ] ;
            layer.path = p ;

            {
                CGColorRef c = [ [ UIColor randomColor ] CGColor ] ;
                layer.fillColor = c ;
                CGColorRelease( c ) ;
            }
            layer.transform = CATransform3DMakeRotation( (CGFloat)index * M_PI_2 - M_PI_4, 0.0, 0.0, 1.0 ) ;
            [ self.layer addSublayer:layer ] ;
        }

        CGPathRelease( p ) ;
    }
}

-(id)initWithFrame:(CGRect)frame
{
    self = [ super initWithFrame:frame ] ;
    [ self addTarget:nil action:@selector( tapped:event: ) forControlEvents:UIControlEventTouchUpInside ] ;
    return self ;
}

-(void)layoutSubviews
{
    [ self _ensureSlices ] ;
    CGRect bounds = self.bounds ;
    self.bounds = (CGRect){ { -0.5f * bounds.size.width, -0.5f * bounds.size.height }, bounds.size } ;
}

-(UIView *)hitTest:(CGPoint)p withEvent:(UIEvent *)e
{
    UIView * result = [ super hitTest:p withEvent:e ] ;
    if ( result == self )
    {
        CGFloat r = sqrt( p.x * p.x + p.y * p.y ) ;
        if ( r < self.innerRadius || r > self.outerRadius )
        {
            return nil ;
        }
    }

    return result ;
}

-(IBAction)tapped:(id)sender event:(UIEvent*)event
{
    CGPoint p = [ [ [ event touchesForView:self ] anyObject ] locationInView:self ] ;

    int index = 0 ;
    for( CAShapeLayer * layer in self.layer.sublayers )
    {
        CGPoint testPoint = [ layer convertPoint:p fromLayer:self.layer ] ;
        if ( CGPathContainsPoint( layer.path, NULL, testPoint, false ) )
        {
            [ self sendMessage:@selector( ringViewTapped:sliceIndex: ) withObject:self withObject:@( index ) ] ;
        }
        ++index ;
    }
}

-(void)setOuterRadius:(CGFloat)r
{
    _outerRadius = r ;
    [[self.layer.sublayers copy ] makeObjectsPerformSelector:@selector( removeFromSuperlayer ) ] ;
    [ self setNeedsLayout ];
}

-(void)setInnerRadius:(CGFloat)r
{
    _innerRadius = r ;
    [[self.layer.sublayers copy ] makeObjectsPerformSelector:@selector( removeFromSuperlayer ) ] ;
    [ self setNeedsLayout ];
}

@end