我有UIView
使用-drawRect:
绘制自己,我想为绘图使用的颜色设置动画。基本的UIView
动画内容由于显而易见的原因(drawRect
)不起作用。
我不能简单地使用CAShapeLayer
来绘制和动画视图内容。我想尝试使用计时器或CADisplayLink
结合setNeedsDisplay
手动伪造动画。有没有一种相当简单的方法来隐藏通常的UIView
动画API背后的魔力?
例如,假设有一个我想要动画的color
属性:
[UIView animateWithDuration:0.2 animations:^{
[customDrawingView setColor:[UIColor redColor]];
}];
有没有办法“拦截”动画调用来读取动画参数(时间,目标值)并手动处理它们?我不想调动UIView
。
答案 0 :(得分:6)
我必须像你这样做过很多次。一般来说,您可以创建一些类来处理浮点插值或CGPoint
插值等内容......并且正确地完成所有操作但是因为整个绘图已经存在,所以它没有多大意义。
因此UIView
animateWithDuration
无效,但您可以添加显示链接并手动进行插值。如果没有更改现有代码,最好只添加几个方法:
假设你现在有这样的东西:
- (void)setColor:(UIColor *)color
{
_color = color;
[self setNeedsDisplay];
}
现在您可以添加setColorAnimated:
并执行所有其他功能:
您需要一些额外的参数(属性),使用您想要的:
UIColor *_sourceColor;
UIColor *_targetColor;
NSDate *_startDate;
NSDate *_endDate;
CADisplayLink *_displayLink;
方法:
- (void)setColorAnimated:(UIColor *)color {
_sourceColor = self.color; // set start to current color
_targetColor = color; // destination color
_startDate = [NSDate date]; // begins currently, you could add some delay if you wish
_endDate = [_startDate dateByAddingTimeInterval:.3]; // will define animation duration
[_displayLink invalidate]; // if one already exists
_displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(onFrame)]; // create the display link
}
- (UIColor *)interpolatedColor:(UIColor *)sourceColor withColor:(UIColor *)targetColor forScale:(CGFloat)scale {
// this will interpolate between two colors
CGFloat r1, g1, b1, a1;
CGFloat r2, g2, b2, a2;
[sourceColor getRed:&r1 green:&g1 blue:&b1 alpha:&a1];
[targetColor getRed:&r2 green:&g2 blue:&b2 alpha:&a2];
// do a linear interpolation on RGBA. You can use other
return [UIColor colorWithRed:r1+(r2-r1)*scale
green:g1+(g2-g1)*scale
blue:b1+(b2-b1)*scale
alpha:a1+(a2-a1)*scale];
}
- (void)onFrame {
// scale is valid between 0 and 1
CGFloat scale = [[NSDate date] timeIntervalSinceDate:_startDate] / [_endDate timeIntervalSinceDate:_startDate];
if(scale < .0f) {
// this can happen if delay is used
scale = .0f;
}
else if(scale > 1.0f)
{
// end animation
scale = 1.0f;
[_displayLink invalidate];
_displayLink = nil;
}
[self setColor:[self interpolatedColor:_sourceColor withColor:_targetColor forScale:scale]];
}
答案 1 :(得分:-1)
通过drawRect创建的动画(淡入)新帧
- (void)drawRect:(CGRect)rect {
CABasicAnimation *animation;
animation = [CABasicAnimation animation];
[animation setDuration:0.5];
[[self layer] addAnimation:animation forKey:@"contents"];
.. your stuff here
}