我需要一些关于在iOS中绘图的建议,更具体地说是关于性能绘制的建议。我在iOS7上阅读了很多关于绘图的文章,但是我没有成功获得正确的结果。
我有点比我需要以正确的顺序链接它们。 感谢我的Dot&弹性类,我成功了这个渲染。我很满意: http://d.pr/v/nYzH
此点代表一张卡片,我需要使用时间轴在每张卡片之间导航。 我使用iCarousel库来实现这个目标。我的工作就像一个UITableView,除了我们管理视图。视图可以重复使用等......
但问题从那里开始。这是结果: http://d.pr/v/y7dq
第一个问题:点的分辨率很低。 第二个真正的问题:我有一些滞后..
你可以按照这里我用来绘制点和点的文件弹性的。
Dot.m文件
@interface Dot () {
CAShapeLayer *_foreground;
CAShapeLayer *_background;
UIBezierPath *_path;
}
@end
@implementation Dot
- (id)initWithPoint:(CGPoint)point andRadius:(CGFloat)radius
{
self = [super init];
if (self) {
self.frame = CGRectMake(point.x, point.y, (radius + 10) * 2, (radius + 10) * 2);
self.radius = radius;
self.color = [UIColor colorWithHexString:@"#FFFFFF"];
[self setPosition:point];
[self setupPath];
_background = [CAShapeLayer layer];
[_background setFrame:CGRectMake(0, 0, self.width, self.height)];
[_background setPath:_path.CGPath];
[self.layer addSublayer:_background];
[self drawStrokedDotToLayer:_background];
_foreground = [CAShapeLayer layer];
[_foreground setFrame:CGRectMake(0, 0, self.width, self.height)];
[_foreground setPath:_path.CGPath];
[self.layer addSublayer:_foreground];
[self drawPlainDotToLayer:_foreground];
[self setBackgroundColor:[UIColor clearColor]];
self.state = DotStateHidden;
}
return self;
}
- (void)setupPath
{
_path = [UIBezierPath bezierPath];
[_path addArcWithCenter:CGPointMake(self.width*.5f, self.height*.5f) radius:self.radius startAngle:0 endAngle:M_PI * 2 clockwise:NO];
}
#pragma mark - Setters
- (void)setPosition:(CGPoint)position
{
self.x = position.x - self.width*.5f;
self.y = position.y - self.width*.5f;
}
- (CGPoint)position
{
return CGPointMake(self.x + self.width*.5f, self.y + self.height*.5f);
}
- (void)setState:(DotState)state
{
_state = state;
CAKeyframeAnimation *foregroundAnim = nil;
CAKeyframeAnimation *backgroundAnim = nil;
switch (_state) {
case DotStateFeedback:
{
self.color = [UIColor colorWithHexString:@"#FFFFFF"];
[self drawFeedback:_foreground];
[self removeGlow:_foreground];
foregroundAnim = [self animation:ScaleIn function:ExponentialEaseOut duration:1.f];
break;
}
case DotStateVisible:
{
self.color = [UIColor colorWithHexString:@"#FFFFFF"];
[self drawPlainDotToLayer:_foreground];
[self drawGlow:_foreground];
[self drawStrokedDotToLayer:_background];
foregroundAnim = [self animation:ScaleIn function:ExponentialEaseOut duration:.2f];
break;
}
case DotStateNext:
{
self.color = [UIColor colorWithHexString:@"#FFFFFF"];
[self drawStrokedDotToLayer:_background];
foregroundAnim = [self animation:ScaleOut function:ExponentialEaseOut duration:.16f];
backgroundAnim = [self animation:ScaleIn function:ExponentialEaseOut duration:.25f];
[foregroundAnim setBeginTime:CACurrentMediaTime() + .04f];
break;
}
case DotStateHidden:
default:
{
self.color = [UIColor colorWithHexString:@"#333333"];
[self drawPlainDotToLayer:_foreground];
[self removeGlow:_foreground];
foregroundAnim = [self animation:ScaleIn function:ExponentialEaseOut duration:.5f];
backgroundAnim = [self animation:ScaleOut function:ExponentialEaseOut duration:.25f];
break;
}
}
if (foregroundAnim) [_foreground addAnimation:foregroundAnim forKey:nil];
if (backgroundAnim) [_background addAnimation:backgroundAnim forKey:nil];
}
#pragma mark - Drawing
- (void)drawStrokedDotToLayer:(CAShapeLayer *)layer
{
[layer setLineWidth:2.f];
[layer setStrokeColor:self.color.CGColor];
[layer setFillColor:[UIColor colorWithHexString:@"#1F1F1F"].CGColor];
}
- (void)drawPlainDotToLayer:(CAShapeLayer *)layer
{
[layer setLineWidth:2.f];
[layer setStrokeColor:[UIColor clearColor].CGColor];
[layer setFillColor:self.color.CGColor];
}
- (void)drawFeedback:(CAShapeLayer *)layer
{
[layer setLineWidth:2.f];
[layer setStrokeColor:[UIColor clearColor].CGColor];
[layer setFillColor:[UIColor colorWithHex:0xFFFFFF andAlpha:.025f].CGColor];
}
- (void)drawGlow:(CAShapeLayer *)layer
{
[layer setShadowRadius:8];
[layer setShadowOpacity:1.f];
[layer setShadowOffset:CGSizeMake(0, 0)];
[layer setShadowColor:[UIColor whiteColor].CGColor];
[layer didChangeValueForKey:@"path"];
}
- (void)removeGlow:(CAShapeLayer *)layer
{
[layer setShadowRadius:0];
[layer setShadowOpacity:0.f];
[layer setShadowOffset:CGSizeMake(0, 0)];
[layer setShadowColor:[UIColor clearColor].CGColor];
[layer didChangeValueForKey:@"path"];
}
- (CAKeyframeAnimation *)animation:(NSInteger)name function:(AHEasingFunction)function duration:(CGFloat)duration
{
CAKeyframeAnimation *animation;
switch (name) {
case ScaleIn:
{
animation = [CAKeyframeAnimation animationWithKeyPath:@"transform.scale" function:function fromValue:0.f toValue:1.f];
break;
}
case ScaleInFeedback:
{
animation = [CAKeyframeAnimation animationWithKeyPath:@"transform.scale" function:function fromValue:0.f toValue:3.f];
break;
}
case ScaleOut:
{
animation = [CAKeyframeAnimation animationWithKeyPath:@"transform.scale" function:function fromValue:1.f toValue:0.f];
break;
}
default:
{
animation = [CAKeyframeAnimation animationWithKeyPath:@"opacity" function:function fromValue:0.f toValue:1.f];
break;
}
}
animation.duration = duration;
animation.fillMode = kCAFillModeForwards;
animation.removedOnCompletion = NO;
return animation;
}
@end
Elastic.m
@interface Elastic () {
UIBezierPath *_path;
UIImage *_image;
}
@end
@implementation Elastic
- (id)initWithDotOne:(Dot *)aDotOne DotTwo:(Dot *)aDotTwo
{
self = [super initWithFrame:[UIScreen mainScreen].bounds];
if (self) {
self.dotOne = aDotOne;
self.dotTwo = aDotTwo;
self.displayDots = NO;
self.feedBack = NO;
self.curveRadius = 4;
[self setBackgroundColor:[UIColor clearColor]];
_path = [UIBezierPath bezierPath];
[self updatePath];
}
return self;
}
- (void)setDisplayDots:(BOOL)displayDots
{
_displayDots = displayDots;
if (_displayDots) {
[self addSubview:self.dotTwo];
} else {
[self.dotTwo removeFromSuperview];
}
}
- (void)drawRect:(CGRect)rect
{
[_image drawInRect:rect];
}
- (void)updatePath
{
// Initialize variables
CGFloat dist = distance(self.dotOne.position, self.dotTwo.position);
CGFloat angle = angleBetweenPoints(self.dotOne.position, self.dotTwo.position) + M_PI * 1.5;
// Points
CGPoint ptA = CGPointMake(
self.dotOne.position.x + cosf(angle) * (self.dotOne.radius - self.curveRadius),
self.dotOne.position.y + sinf(angle) * (self.dotOne.radius - self.curveRadius)
);
CGPoint ptB = CGPointMake(
self.dotOne.position.x + cosf(angle + M_PI) * (self.dotOne.radius - self.curveRadius),
self.dotOne.position.y + sinf(angle + M_PI) * (self.dotOne.radius - self.curveRadius)
);
CGPoint ptC = CGPointMake(
self.dotTwo.position.x + cosf(angle) * (self.dotTwo.radius - self.curveRadius),
self.dotTwo.position.y + sinf(angle) * (self.dotTwo.radius - self.curveRadius)
);
CGPoint ptD = CGPointMake(
self.dotTwo.position.x + cosf(angle + M_PI) * (self.dotTwo.radius - self.curveRadius),
self.dotTwo.position.y + sinf(angle + M_PI) * (self.dotTwo.radius - self.curveRadius)
);
// Bezier
CGFloat mapA = angle + M_PI_2 + map(dist, 150, 350, 0.0001, 0.0005);
CGFloat mapB = angle + M_PI_2 - map(dist, 150, 350, 0.0001, 0.0005);
CGPoint bzA = CGPointMake(self.dotOne.position.x + cosf(mapA) * dist*.5f, self.dotOne.position.y + sinf(mapA) * dist*.5f);
CGPoint bzB = CGPointMake(self.dotOne.position.x + cosf(mapB) * dist*.5f, self.dotOne.position.y + sinf(mapB) * dist*.5f);
// Start drawing path
[_path moveToPoint:ptA];
[_path addQuadCurveToPoint:ptC controlPoint:bzA];
[_path addLineToPoint:ptD];
[_path addQuadCurveToPoint:ptB controlPoint:bzB];
[self drawBitmap];
[self setNeedsDisplay];
}
- (void)drawBitmap
{
_image = nil;
UIGraphicsBeginImageContextWithOptions(self.bounds.size, NO, 0.0);
[_image drawAtPoint:CGPointZero];
[[UIColor whiteColor] setFill];
[_path fill];
_image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
[_path removeAllPoints];
}
@end
答案 0 :(得分:0)
您的视频看起来好像是在模拟器上录制的,而不是设备上录制的。模拟器测试对于性能,尤其是图形性能毫无意义,因为模拟器无法使用专用GPU。
由于这个原因,模拟器上的GPU操作通常比设备差很多。所以,我可以提供以下建议:
如果您喜欢iCarousel,那么该项目的作者Nick Lockwood就iOS的核心动画有一本很好的书,其中包含一章关于性能调优的内容。