我有一个 UIImageView,我想以径向顺时针方式慢慢显示。
这是我想如何在 1 秒内显示图像的示例。我基本上是在尝试模拟一个标记在某物周围画一个圆圈。
我有一个 UIImageView,我想以径向顺时针方式慢慢显示。
这是我想如何在 1 秒内显示图像的示例。我基本上是在尝试模拟一个标记在某物周围画一个圆圈。
这是动画 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"];
}
你显然必须创建你的贝塞尔曲线。这是我复杂的小算法(它是一个由五个点组成的数组,每个点的角度,以及每个点的锚点的权重),但我相信你可以想出一些更简单的东西:
- (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(或其他),然后拍摄另一个屏幕快照等)。
希望有人能想出一个更优雅的解决方案!