2

放射状の時計回りにゆっくりと明らかにしたい UIImageView があります。

これは、1秒間に画像を表示する方法の例です。基本的に、何かの周りに円を描くマーカーをシミュレートしようとしています。

放射状画像の例

4

1 に答える 1

4

a のアニメーション化の別のバリエーションを次に示しUIBezierPathます。要するに、UIBezierPath を考え出し、その描画を次の でアニメーション化するだけCABasicAnimationですstrokeEnd

- (void)drawBezier
{
    CGPoint startPoint = CGPointMake(self.view.frame.size.width / 2.0, 50);

    UIBezierPath *path = [self strokePath:startPoint];

    CAShapeLayer *oval = [[CAShapeLayer alloc] init];
    oval.path = path.CGPath;
    oval.strokeColor = [UIColor redColor].CGColor;
    oval.fillColor = [UIColor clearColor].CGColor;
    oval.lineWidth = 5.0;
    oval.strokeStart = 0.0;
    oval.strokeEnd = 1.0;
    [self.view.layer addSublayer:oval];

    CABasicAnimation *anim = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
    anim.duration = 1.0;
    anim.fromValue = [NSNumber numberWithFloat:0.0f];
    anim.toValue = [NSNumber numberWithFloat:1.0f];
    [oval addAnimation:anim forKey:@"strokeEndAnimation"];
}

明らかに、ベジエを作成する必要があります。これは私の複雑で小さなアルゴリズムです (これは 5 つのポイント、各ポイントの角度、および各ポイントのアンカー ポイントの重みの配列です) が、もっと簡単なものを思い付くことができると確信しています:

- (UIBezierPath *)strokePath:(CGPoint)startPoint
{
    NSArray *points = [NSArray arrayWithObjects:
                       [NSValue valueWithCGPoint:CGPointMake(startPoint.x, startPoint.y)], 
                       [NSValue valueWithCGPoint:CGPointMake(startPoint.x + 100.0, startPoint.y + 70.0)], 
                       [NSValue valueWithCGPoint:CGPointMake(startPoint.x, startPoint.y + 140.0)], 
                       [NSValue valueWithCGPoint:CGPointMake(startPoint.x - 100.0, startPoint.y + 70.0)], 
                       [NSValue valueWithCGPoint:CGPointMake(startPoint.x + 10.0, startPoint.y + 10)], 
                       nil];
    NSArray *angles = [NSArray arrayWithObjects:
                       [NSNumber numberWithFloat:M_PI_2 * 0.05],
                       [NSNumber numberWithFloat:M_PI_2],
                       [NSNumber numberWithFloat:M_PI],
                       [NSNumber numberWithFloat:M_PI_2 * 3],
                       [NSNumber numberWithFloat:0],
                       nil];
    NSArray *weight = [NSArray arrayWithObjects:
                       [NSNumber numberWithFloat:100.0 / 1.7],
                       [NSNumber numberWithFloat: 70.0 / 1.7],
                       [NSNumber numberWithFloat:100.0 / 1.7],
                       [NSNumber numberWithFloat: 70.0 / 1.7],
                       [NSNumber numberWithFloat:100.0 / 1.7],
                       nil];

    UIBezierPath *path = [UIBezierPath bezierPath];
    [path moveToPoint:startPoint];

    for (NSInteger i = 1; i < 5; i++)
    {
        CGPoint pointPrevious  = [[points objectAtIndex:(i-1)] CGPointValue];
        CGPoint pointCurrent   = [[points objectAtIndex:i] CGPointValue];

        CGFloat anglePrevious  = [[angles objectAtIndex:(i-1)] floatValue];
        CGFloat angleCurrent   = [[angles objectAtIndex:i] floatValue];

        CGFloat weightPrevious = [[weight objectAtIndex:(i-1)] floatValue];
        CGFloat weightCurrent  = [[weight objectAtIndex:i] floatValue];

        [path addCurveToPoint:pointCurrent
                controlPoint1:CGPointMake(pointPrevious.x + cosf(anglePrevious) * weightPrevious, 
                                          pointPrevious.y + sinf(anglePrevious) * weightPrevious) 
                controlPoint2:CGPointMake(pointCurrent.x  - cosf(angleCurrent)  * weightCurrent,  
                                          pointCurrent.y  - sinf(angleCurrent)  * weightCurrent)];
    }

    return path;
}

これが受け入れられない場合 (芸術的なレンダリングではなく堅実なパスであるため)、ここに機能するトリックがあります (ただし、少し複雑なので、我慢してください)。画像をレイヤーに配置し、UIBezierPath の楕円をその上に配置し、ベジエ パスの描画を赤でアニメーション化するのではなく、白で描画して画像を覆い隠し、背景に溶け込ませ、アニメーションを逆にすることができますUIBezierPath の描画。そうすれば、画像の上に白い UIBezierPath が描画され、画像が完全に覆い隠され、UIBezierPath の描画解除がアニメーション化され、下の画像が表示されます。とにかく、これはレイヤーに画像を追加する方法と、ベジエを「描画解除」する方法です。

    CAShapeLayer *imagelayer = [[CAShapeLayer alloc] init];
    UIImage *image = [UIImage imageNamed:@"oval.png"];
    imagelayer.contents = (id)image.CGImage;
    imagelayer.frame = CGRectMake(startPoint.x - image.size.width / 2.0, startPoint.y, image.size.width, image.size.height);
    [self.view.layer addSublayer:imagelayer];

    CAShapeLayer *oval = [[CAShapeLayer alloc] init];
    oval.path = path.CGPath;
    oval.strokeColor = [UIColor whiteColor].CGColor;
    oval.fillColor = [UIColor clearColor].CGColor;
    oval.lineWidth = 80.0;
    oval.strokeStart = 0.0;
    oval.strokeEnd = 0.0;
    [self.view.layer addSublayer:oval];

    CABasicAnimation *anim = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
    anim.duration = 1.0;
    anim.fromValue = [NSNumber numberWithFloat:1.0f];
    anim.toValue = [NSNumber numberWithFloat:0.0f];
    [oval addAnimation:anim forKey:@"strokeEndAnimation"];

明らかに、画像などを直接覆う UIBezierPath を考え出すにはいくらかの努力が必要ですが、それは可能です。(ちなみに、この演習は、(a) UIBezier を描画し、(b) 画面のスナップショットを取り、(c) それを Photoshop に投入して、必要な外観に仕上げ、(d)とにかく、下の私の大雑把な試みでは、ベジエの厚さを信じられないほど厚くしたので、かなりずさんになる可能性がありますが、もっと注意する必要があります(私はあなたが何かの周りに円を描くと、UIBezierPath オーバーレイがそれを覆い隠すことはできません)。

または、CodaFi の最初の提案を使用したいが、個々の画像をまだ作成していない場合は、この超太いベジエ パスを使用できますが、上記のコードの順列を使用して画像を作成できます (例: startゼロのstrokeStart場合、アニメーション化するのではなく、画面のスナップショットを撮り、何度も繰り返して、strokeStart毎回 1/30 (または何でも) ずつ増やして、別の画面のスナップショットを撮るなど)。

うまくいけば、誰かがよりエレガントなソリューションを考え出すことができます!

于 2012-07-13T05:37:43.047 に答える