最近在看《iOS 6 Programming Cookbook》的翻譯版,它由DevDiv論壇的網友翻譯,原文地址:點擊跳轉。由于下載的pdf都有水印,并且排版不是很好,特別是代碼排版,基本不能看,所以這里就整理了一下,方便再次查看。另外把里面提到的點寫了一個demo,由于里面一些代碼現在已經廢棄,所以demo中都是用的新api,下載地址在這里:圖形與動畫Demo。
1.5 畫線
如何使用路徑 創建直線。為此,請遵照以下步驟:
- 在你的圖形環境選擇一個顏色。
- 使用
UIGraphicsGetCurrentContext
函數,獲得圖形環境的句柄。 - 使用
CGContextMoveToPoint
函數設置線的起點。 - 使用
CGContextAddLineToPoint
函數移動圖形環境的畫筆,來指定線的終點。 - 使用
CGContextStrokePath
函數創建你的路徑。這個過程將使用圖形環境當前設置的
顏色來繪制路徑。 可選的,你可以使用CGContextSetLineWidth
來設置線的寬度。這個方法的第一個參數是圖形環境,第二個參數是線的寬度——浮點型(CGFloat)。
在 iOS 中,線的寬度以邏輯點為單位計量。
下面是一個示例:
- (void)drawRect:(CGRect)rect
{
/* Set the color that we want to use to draw the line */
[[UIColor brownColor] set];
/* Get the current graphics context */
CGContextRef currentContext = UIGraphicsGetCurrentContext(); /* Set the width for the line */
CGContextSetLineWidth(currentContext,5.0f);
/* Start the line at this point */
CGContextMoveToPoint(currentContext,50.0f,10.0f);
/* And end it at this point */
CGContextAddLineToPoint(currentContext, 100.0f,200.0f);
/* Use the context's current color to draw the line */
CGContextStrokePath(currentContext);
}
那么如何接著在(100,100)這個點接著畫一條到(300,100)的線呢,在你調用完使用畫筆的方法后,它會將畫筆留在它 繪制的終點,你只需要用另一個終點,再次調用 CGContextAddLineToPoint
過程,下面是示 例代碼:
- (void)drawRect:(CGRect)rect
{
// Drawing code
/* Set the color that we want to use to draw the line */
[[UIColor brownColor] set];
/* Get the current graphics context */
CGContextRef currentContext = UIGraphicsGetCurrentContext(); /* Set the width for the lines */
CGContextSetLineWidth(currentContext, 5.0f);
/* Start the line at this point */
CGContextMoveToPoint(currentContext, 20.0f,20.0f);
/* And end it at this point */
CGContextAddLineToPoint(currentContext,100.0f,100.0f);
/* Extend the line to another point */
CGContextAddLineToPoint(currentContext, 300.0f,100.0f);
/* Use the context's current color to draw the lines */
CGContextStrokePath(currentContext);
}
兩條線相遇的點,毫不意外,被稱為接合點(join)。使用 Core Graphics
,你可以指定 線和線之間接合點的類型。要設置自己的接合點類型,你必須調用 CGContextSetLineJoin
過 程。它接受兩個參數:圖形環境和接合點類型,類型必須是 CGLineJoin
類型。CGLineJoin
有以下枚舉值:
kCGLineJoinMiter
接合點為尖角。這是默認的接合類型。
kCGLineJoinBevel
接合點為斜角
kCGLineJoinRound
接合點為圓角
效果如下圖所示:
為了完成這個,我寫了一個名為drawRooftopAtTopPointof:text ToDisplay:lineJoin:
的方 法,它接受三個參數:
- 一個點,屋頂的頂部在這一點
- 屋頂內顯示的文字
- 要使用的接合類型
下面是代碼:
- (void) drawRooftopAtTopPointof:(CGPoint)paramTopPoint textToDisplay:(NSString *)paramText lineJoin:(CGLineJoin)paramLineJoin{
/* Set the color that we want to use to draw the line */ [[UIColor brownColor] set];
/* Get the current graphics context */
CGContextRef currentContext = UIGraphicsGetCurrentContext(); /* Set the line join */
CGContextSetLineJoin(currentContext,paramLineJoin);
/* Set the width for the lines */
CGContextSetLineWidth(currentContext,20.0f);
/* Start the line at this point */
CGContextMoveToPoint(currentContext,paramTopPoint.x - 140,paramTopPoint.y + 100);
/* And end it at this point */
CGContextAddLineToPoint(currentContext,paramTopPoint.x,paramTopPoint.y);
/* Extend the line to another point to
make the rooftop */
CGContextAddLineToPoint(currentContext,paramTopPoint.x + 140,paramTopPoint.y + 100);
/* Use the context's current color to draw the lines */
CGContextStrokePath(currentContext);
/* Draw the text in the rooftop using a black color */
[[UIColor blackColor] set];
/* Now draw the text */
CGPoint drawingPoint = CGPointMake(paramTopPoint.x - 40.0f, paramTopPoint.y + 60.0f);
[paramText drawAtPoint:drawingPoint
withFont:[UIFont boldSystemFontOfSize:30.0f]];
}
現在,我們在視圖對象的 drawRect:
方法中,調用這個方法:
- (void)drawRect:(CGRect)rect{
[self drawRooftopAtTopPointof:CGPointMake(160.0f, 40.0f) textToDisplay:@"Miter"
lineJoin:kCGLineJoinMiter];
[self drawRooftopAtTopPointof:CGPointMake(160.0f, 180.0f) textToDisplay:@"Bevel"
lineJoin:kCGLineJoinBevel];
[self drawRooftopAtTopPointof:CGPointMake(160.0f, 320.0f) textToDisplay:@"Round"
lineJoin:kCGLineJoinRound];
}
1.6 構造路徑
路徑屬于他們被繪制的圖形環境。路徑沒有邊界或者指定的形狀,而不像在其上繪制的形狀那樣。不過路徑確實有邊界矩形(bounding boxes)。請記住,范圍(boundaries)不同于邊界矩形。范圍是一種限制,超出了它你就不能往畫布上繪圖,而路徑的邊界矩形是包含已經被畫到指定路徑上的所有的形狀,點和其他對象的最小矩形。你可以把路徑看做郵票, 而把圖形環境當成信封。每次你給朋友寫信的時候,信封可以是相同的,但是你往環境上放 置的東西(郵票或路徑)可以不同。
在你完成一條路徑的繪制后,你可以將它畫到圖形環境上。熟悉游戲編程的開發者知道 緩沖(buffers)的概念,他們繪制場景并且在適當的時間,將圖像輸出(flush)到屏幕。路徑 就是這些緩沖。他們就像可以在恰當的時間,被繪制到圖形環境上的空畫布。
直接操作路徑的第一步就是創建他們。創建路徑的方法返回一個句柄,你可以在你想往 路徑上畫點東西的時候使用它,將句柄傳給core graphics
可以得到路徑的引用。在你創建路 徑后,你可以往上面加不同的點,線和形狀,然后繪制這條路徑。你可以在圖形環境上填充 路徑,或者用畫筆畫出它。下面是你要使用的一些方法:
CGPathCreateMutable 函數
創建一個新的 CGMutablePathRef 類型的可變路徑并返回其句柄。我們應該在操作完成 后處理它,你后面會看到。
CGPathMoveToPoint 過程
將路徑上當前畫筆位置移動到 CGPoint 類型的參數指定的點。
CGPathAddLineToPoint 過程
從畫筆當前位置向指定位置繪制一條線段。
CGContextAddPath 過程
向圖形環境上添加一個路徑(由一個路徑句柄指定),該路徑已經準備好被繪制。
CGContextDrawPath 過程
在圖形環境上繪制指定路徑
CGPathRelease 過程
釋放為路徑句柄所分配的內存。
CGPathAddRect 過程
向路徑添加一個矩形。這個矩形由 CGRect 結構指定。
你可以要求 CGContextDrawPath 過程執行三種重要的繪制方法:
kCGPathStroke
畫線來標記路徑的邊界或邊緣,使用選中的繪圖色。
kCGPathFill
用選中的填充色,填充被路徑包圍的區域。
kCGPathFillStroke
組合繪圖和填充。用當前填充色填充路徑,并用當前繪圖色繪制路徑邊界。下面我們會看到一個使用此方法的例子。
- (void)drawRect:(CGRect)rect
{
/* Create the path */
CGMutablePathRef path = CGPathCreateMutable();
/* How big is the screen? We want the X to cover
the whole screen */
CGRect screenBounds = [[UIScreen mainScreen] bounds];
/* Start from top-left */
CGPathMoveToPoint(path,
NULL,
screenBounds.origin.x,
screenBounds.origin.y);
/* Draw a line from top-left to bottom-right of the screen */
CGPathAddLineToPoint(path,
NULL,
screenBounds.size.width,
screenBounds.size.height);
/* Start another line from top-right */
CGPathMoveToPoint(path,
NULL,
screenBounds.size.width,
screenBounds.origin.y);
/* Draw a line from top-right to bottom-left */
CGPathAddLineToPoint(path,
NULL,
screenBounds.origin.x,
screenBounds.size.height);
/* Get the context that the path has to be drawn on */
CGContextRef currentContext = UIGraphicsGetCurrentContext();
/* Add the path to the context so we can
draw it later */
CGContextAddPath(currentContext,path);
/* Set the blue color as the stroke color */
[[UIColor blueColor] setStroke];
/* Draw the path with stroke color */
CGContextDrawPath(currentContext,kCGPathStroke);
/* Finally release the path object */
CGPathRelease(path);
}
傳給 CGPathMoveToPoint
之類的過程的 NULL
參數,代表了在給定路徑上繪制形狀和線時可能用到的變換.
1.7 繪制矩形
用 CGPathAddRect
向路徑中添加一個矩形,然后在圖形環境上繪制這條路徑。
- (void)drawRect:(CGRect)rect
{
/* Create the path first. Just the path handle. */
CGMutablePathRef path = CGPathCreateMutable();
/* Here are the rectangle boundaries */
CGRect rectangle = CGRectMake(10.0f, 80.0f, 200.0f, 300.0f);
/* Add the rectangle to the path */
CGPathAddRect(path, NULL, rectangle);
/* Get the handle to the current context */
CGContextRef currentContext = UIGraphicsGetCurrentContext();
/* Add the path to the context */
CGContextAddPath(currentContext,path);
/* Set the fill color to cornflower blue */
[[UIColor colorWithRed:0.20f green:0.60f blue:0.80f alpha:1.0f] setFill];
/* Set the stroke color to brown */
[[UIColor brownColor] setStroke];
/* Set the line width (for the stroke) to 5 */
CGContextSetLineWidth(currentContext, 5.0f);
/* Stroke and fill the path on the context */
CGContextDrawPath(currentContext, kCGPathFillStroke);
/* Dispose of the path */
CGPathRelease(path);
}
這里在路徑上畫了一個矩形,用矢車菊藍填充它,并用棕色描出了矩形的邊緣。
如果你有多個矩形要繪制,你可以向
CGPathAddRects
過程傳遞一個 CGrect
對象的數組,如下:
- (void)drawRect:(CGRect)rect
{
/* Create the path first. Just the path handle. */
CGMutablePathRef path = CGPathCreateMutable();
/* Here are the first rectangle boundaries */
CGRect rectangle1 = CGRectMake(10.0f, 10.0f, 200.0f, 300.0f);
/* And the second rectangle */
CGRect rectangle2 = CGRectMake(40.0f, 100.0f, 90.0f, 300.0f);
/* Put both rectangles into an array */
CGRect rectangles[2] = {
rectangle1, rectangle2
};
/* Add the rectangles to the path */
CGPathAddRects(path, NULL, (const CGRect *)&rectangles, 2);
/* Get the handle to the current context */
CGContextRef currentContext = UIGraphicsGetCurrentContext();
/* Add the path to the context */
CGContextAddPath(currentContext,path);
/* Set the fill color to cornflower blue */
[[UIColor colorWithRed:0.20f green:0.60f blue:0.80f alpha:1.0f] setFill];
/* Set the stroke color to black */
[[UIColor blackColor] setStroke];
/* Set the line width (for the stroke) to 5 */
CGContextSetLineWidth(currentContext, 5.0f);
/* Stroke and fill the path on the context */
CGContextDrawPath(currentContext, kCGPathFillStroke);
/* Dispose of the path */
CGPathRelease(path);
}
我們傳給 CGPathAddRects
過程的參數有:
- 要添加矩形的路徑句柄
- 變換,如果有的話,應用到矩形上。
- CGRect 數組的引用
- 前一個參數中數組的大小。你傳入的這個參數一定要和矩形數相等,以避免此過程出 現未知的行為。