我想在显示数值数据的UIView中制作图表。所以我需要绘制轴,一些坐标线,一些刻度线,然后将数据绘制为连接的直线。数据通常可以包括-500范围内的几百个x值。到+1000。相应的y值在300到350之间。
所以我认为一个好的方法是转换UIView的坐标(对于给出的示例值),视图的左侧是-500,右侧是1000,顶部是400,底部是300. y向上增加。然后在drawRect:我可以使用我自己的坐标系编写一堆CGContextMoveToPoint()和CGContextAddLineToPoint()语句,而不必在心理上将每个调用转换为UIView坐标。
我编写了以下函数来生成我自己的CGContextRef,但它没有达到我的预期。我已经尝试了几天的变化,浪费了这么多时间。有人可以说如何解决它?我意识到我无法清楚地知道变换是否应该根据我的坐标指定UIView坐标,反之亦然,或完全不同。
static inline CGContextRef myCTX(CGRect rect, CGFloat xLeft, CGFloat xRight, CGFloat yBottom, CGFloat yTop) {
CGAffineTransform ctxTranslate = CGAffineTransformMakeTranslation(xLeft, rect.size.height - yTop);
CGAffineTransform ctxScale = CGAffineTransformMakeScale( rect.size.width / (xRight - xLeft), -rect.size.height / (yTop - yBottom) ); //minus so y increases toward top
CGAffineTransform combinedTransform = CGAffineTransformConcat(ctxTranslate, ctxScale);
CGContextRef c = UIGraphicsGetCurrentContext();
CGContextConcatCTM(c, combinedTransform);
return c;
}
我使用它的方式是在drawRect中我只有:
CGContextRef ctx = myCTX(rect, self.xLeft, self.xRight, self.yBottom, self.yTop);
然后是一系列陈述,如:
CGContextAddLineToPoint(ctx, [x[i] floatValue], [y[i] floatValue]);
答案 0 :(得分:1)
我通过实验来解决这个问题。转换需要3个步骤而不是2步(或者,如果不需要,至少它以这种方式工作):
static inline CGContextRef myCTX(CGRect rect, CGFloat xLeft, CGFloat xRight, CGFloat yBottom, CGFloat yTop) {
CGAffineTransform translate1 = CGAffineTransformMakeTranslation(-xLeft, -yBottom);
CGAffineTransform scale = CGAffineTransformMakeScale( rect.size.width / (xRight - xLeft), -rect.size.height / (yTop - yBottom) );
CGAffineTransform transform = CGAffineTransformConcat(translate1, scale);
CGAffineTransform translate2 = CGAffineTransformMakeTranslation(1, rect.size.height);
transform = CGAffineTransformConcat(transform, translate2);
CGContextRef c = UIGraphicsGetCurrentContext();
CGContextConcatCTM(c, transform);
return c;
}
您在drawRect中使用此功能。在我的例子中,xLeft,xRight等值是UIView子类的属性,由viewController设置。所以视图的drawRect看起来像这样:
- (void)drawRect:(CGRect)rect
{
CGContextRef c = UIGraphicsGetCurrentContext();
CGContextSaveGState(c);
CGContextRef ctx = myCTX(rect, self.xLeft, self.xRight, self.yBottom, self.yTop);
…
all of the CGContextMoveToPoint(), CGContextAddLineToPoint(), calls to
draw your desired lines, rectangles, curves, etc. but not stroke or fill them
…
CGContextRestoreGState(c);
CGContextSetLineWidth(c, 1);
CGContextStrokePath(c);
}
如果您希望线宽为1,则不需要CGContextSetLineWidth调用。如果您不在strokePath之前恢复图形状态,则路径宽度会受到缩放的影响。
现在我必须弄清楚如何在视图上绘制文字。