iOS開發必會的座標系探究
歡迎大家前往騰訊雲+社群,獲取更多騰訊海量技術實踐乾貨哦~
前言
app在渲染檢視時,需要在座標系中指定繪製區域。 這個概念看似乎簡單,事實並非如此。
When an app draws something in iOS, it has to locate the drawn content in a two-dimensional space defined by a coordinate system. This notion might seem straightforward at first glance, but it isn’t.
正文
我們先從一段最簡單的程式碼入手,在drawRect中顯示一個普通的UILabel; 為了方便判斷,我把整個view的背景設定成黑色:
- (void)drawRect:(CGRect)rect {
[super drawRect:rect];
CGContextRef context = UIGraphicsGetCurrentContext();
NSLog(@"CGContext default CTM matrix %@", NSStringFromCGAffineTransform(CGContextGetCTM(context)));
UILabel *testLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 100, 28)] ;
testLabel.text = @"測試文字";
testLabel.font = [UIFont systemFontOfSize:14];
testLabel.textColor = [UIColor whiteColor];
[testLabel.layer renderInContext:context];
}
這段程式碼首先建立一個UILabel,然後設定文字,顯示到螢幕上,沒有修改座標。 所以按照UILabel.layer預設的座標(0, 0),在左上角進行了繪製。
UILabel繪製
接著,我們嘗試使用CoreText來渲染一段文字。
- (void )drawRect:(CGRect)rect {
[super drawRect:rect];
CGContextRef context = UIGraphicsGetCurrentContext();
NSLog(@"CGContext default matrix %@", NSStringFromCGAffineTransform(CGContextGetCTM(context)));
NSAttributedString *attrStr = [[NSAttributedString alloc] initWithString:@"測試文字" attributes:@{
NSForegroundColorAttributeName:[UIColor whiteColor],
NSFontAttributeName:[UIFont systemFontOfSize:14],
}];
CTFramesetterRef frameSetter = CTFramesetterCreateWithAttributedString((__bridge CFAttributedStringRef) attrStr); // 根據富文字建立排版類CTFramesetterRef
UIBezierPath * bezierPath = [UIBezierPath bezierPathWithRect:CGRectMake(0, 0, 100, 20)];
CTFrameRef frameRef = CTFramesetterCreateFrame(frameSetter, CFRangeMake(0, 0), bezierPath.CGPath, NULL); // 建立排版資料
CTFrameDraw(frameRef, context);
}
首先用NSString建立一個富文字,然後根據富文字建立CTFramesetterRef,結合CGRect生成的UIBezierPath,我們得到CTFrameRef,最終渲染到螢幕上。 但是結果與上文不一致:文字是上下顛倒。
CoreText的文字繪製
從這個不同的現象開始,我們來理解iOS的座標系。
座標系概念
在iOS中繪製圖形必須在一個二維的座標系中進行,但在iOS系統中存在多個座標系,常需要處理一些座標系的轉換。 先介紹一個圖形上下文(graphics context)的概念,比如說我們常用的CGContext就是Quartz 2D的上下文。圖形上下文包含繪製所需的資訊,比如顏色、線寬、字型等。用我們在Windows常用的畫圖來參考,當我們使用畫筆