ios - 使用径向动画显示 UIImage

标签 ios uiimageview uiimage

我有一个 UIImageView,我想以径向顺时针方式慢慢显示。

下面是我想要如何在 1 秒内显示图像的示例。我基本上是想模拟一个标记在某物周围画一个圆圈。

Radial Image Example

最佳答案

这是 UIBezierPath 动画的另一种变体。最重要的是,提出一个 UIBezierPath,然后使用 StrokeEndCABasicAnimation 对它的绘制进行动画处理:

- (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"];
}

你显然必须创建你的贝塞尔曲线。这是我的复杂的小算法(它是一个由五个点组成的数组,每个点的角度以及每个点的 anchor 的权重),但我相信您可以想出更简单的算法:

- (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;
}

如果这是 Not Acceptable (因为它是一条坚实的路径,而不是你的艺术渲染),这里有一个有效的技巧(但有点复杂,所以请耐心等待)。您可以将图像放在图层上,将 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 的第一个建议,但尚未创建单个图像,您可以坚持使用这个超厚的贝塞尔路径,但您可以使用上面代码的排列来创建图像(例如,从 0 开始,不进行动画处理,而是拍摄屏幕快照,一遍又一遍地执行,将 1/30 增加 1/30(或无论如何)每次,并拍摄另一个屏幕快照等)。

希望有人能提出更优雅的解决方案!

关于ios - 使用径向动画显示 UIImage,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11458605/

相关文章:

ios - Parse 中要删除的对象太多,阻止 UI : Doesnt respond, 取消删除

iOS联系人如何通过电话号码获取联系人

iphone - 使用图像倒计时

iphone - 如何通过拖动边缘右角来增大或减小UIImageView的尺寸?

ios - 将彩色 UIImageView 添加到 UITableViewCell 时的奇怪行为

javascript - 输入新字符后获取 contentEditable div 高度

ios - 性能差异 : loadNibNamed vs. 以编程方式

ios - 将 PNG 保存到磁盘,但将文件路径保存到核心数据

swift - iOS 12 中压缩图像。这段代码将如何更新?

ios - 在给定时间捕获 AVPlayer 流 .m3u8 的 UIImage 帧?