Нам нужно посмотреть, как вы строите UIBezierPath
, но по моему опыту, для гладких кривых ключевой вопрос заключается в том, равен ли наклон линии между контрольной точкой кривой и конечной точкой этого конкретного сегмента кривой наклон между следующим сегментом начальной точки кривой и ее контрольной точкой. Я считаю, что проще рисовать общие плавные кривые, используя addCurveToPoint
, а не addQuadCurveToPoint
, так что я могу настроить начальную и конечную контрольные точки, чтобы удовлетворить этому критерию в более общем плане.
Чтобы проиллюстрировать это, я обычно рисую кривые UIBezierPath
так, чтобы иметь массив точек на кривой, угол, который должна принимать кривая в этой точке, а затем "вес" контрольных точек addCurveToPoint
(т.е. контрольные точки должны быть). Таким образом, я использую эти параметры, чтобы указать вторую контрольную точку UIBezierPath
и первую контрольную точку следующего сегмента UIBezierPath
. Так, например:
@interface BezierPoint : NSObject
@property CGPoint point;
@property CGFloat angle;
@property CGFloat weight;
@end
@implementation BezierPoint
- (id)initWithPoint:(CGPoint)point angle:(CGFloat)angle weight:(CGFloat)weight
{
self = [super init];
if (self)
{
self.point = point;
self.angle = angle;
self.weight = weight;
}
return self;
}
@end
И затем, пример того, как я это использую:
- (void)loadBezierPointsArray
{
// clearly, you'd do whatever is appropriate for your chart.
// this is just a unclosed loop. But it illustrates the idea.
CGPoint startPoint = CGPointMake(self.view.frame.size.width / 2.0, 50);
_bezierPoints = [NSMutableArray arrayWithObjects:
[[BezierPoint alloc] initWithPoint:CGPointMake(startPoint.x, startPoint.y)
angle:M_PI_2 * 0.05
weight:100.0 / 1.7],
[[BezierPoint alloc] initWithPoint:CGPointMake(startPoint.x + 100.0, startPoint.y + 70.0)
angle:M_PI_2
weight:70.0 / 1.7],
[[BezierPoint alloc] initWithPoint:CGPointMake(startPoint.x, startPoint.y + 140.0)
angle:M_PI
weight:100.0 / 1.7],
[[BezierPoint alloc] initWithPoint:CGPointMake(startPoint.x - 100.0, startPoint.y + 70.0)
angle:M_PI_2 * 3.0
weight:70.0 / 1.7],
[[BezierPoint alloc] initWithPoint:CGPointMake(startPoint.x + 10.0, startPoint.y + 10)
angle:0.0
weight:100.0 / 1.7],
nil];
}
- (CGPoint)calculateForwardControlPoint:(NSUInteger)index
{
BezierPoint *bezierPoint = _bezierPoints[index];
return CGPointMake(bezierPoint.point.x + cosf(bezierPoint.angle) * bezierPoint.weight,
bezierPoint.point.y + sinf(bezierPoint.angle) * bezierPoint.weight);
}
- (CGPoint)calculateReverseControlPoint:(NSUInteger)index
{
BezierPoint *bezierPoint = _bezierPoints[index];
return CGPointMake(bezierPoint.point.x - cosf(bezierPoint.angle) * bezierPoint.weight,
bezierPoint.point.y - sinf(bezierPoint.angle) * bezierPoint.weight);
}
- (UIBezierPath *)bezierPath
{
UIBezierPath *path = [UIBezierPath bezierPath];
BezierPoint *bezierPoint = _bezierPoints[0];
[path moveToPoint:bezierPoint.point];
for (NSInteger i = 1; i < [_bezierPoints count]; i++)
{
bezierPoint = _bezierPoints[i];
[path addCurveToPoint:bezierPoint.point
controlPoint1:[self calculateForwardControlPoint:i - 1]
controlPoint2:[self calculateReverseControlPoint:i]];
}
return path;
}
Когда я визуализирую это в UIImage
(используя приведенный ниже код), я не вижу никакого смягчения изображения, но надо признать, что изображения не идентичны. (Я сравниваю изображение, созданное capture
, с изображением, которое я сделал вручную, с помощью снимка экрана, одновременно нажав кнопки питания и «Домой» на моем физическом устройстве.)
Если вы видите некоторое смягчение, я бы предложил renderInContext
(как показано ниже). Интересно, пишете ли вы изображение в формате JPG (с потерями). Может быть, попробуйте PNG, если вы использовали JPG.
- (void)drawBezier
{
UIBezierPath *path = [self bezierPath];
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];
}
- (void)capture
{
UIGraphicsBeginImageContextWithOptions(self.view.frame.size, NO, 0.0);
CGContextRef context = UIGraphicsGetCurrentContext();
[self.view.layer renderInContext:context];
UIImage *screenshot = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
// save the image
NSData *data = UIImagePNGRepresentation(screenshot);
NSString *documentsPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0];
NSString *imagePath = [documentsPath stringByAppendingPathComponent:@"image.png"];
[data writeToFile:imagePath atomically:YES];
// send it to myself so I can look at the file
NSURL *url = [NSURL fileURLWithPath:imagePath];
UIActivityViewController *controller = [[UIActivityViewController alloc] initWithActivityItems:@[url]
applicationActivities:nil];
[self presentViewController:controller animated:YES completion:nil];
}
person
Rob
schedule
24.12.2012