圖形與動畫(二)--附Demo

最近在看《iOS 6 Programming Cookbook》的翻譯版,它由DevDiv論壇的網友翻譯,原文地址:點擊跳轉。由于下載的pdf都有水印,并且排版不是很好,特別是代碼排版,基本不能看,所以這里就整理了一下,方便再次查看。另外把里面提到的點寫了一個demo,由于里面一些代碼現在已經廢棄,所以demo中都是用的新api,下載地址在這里:圖形與動畫Demo

1.5 畫線

如何使用路徑 創建直線。為此,請遵照以下步驟:

  1. 在你的圖形環境選擇一個顏色。
  2. 使用 UIGraphicsGetCurrentContext 函數,獲得圖形環境的句柄。
  3. 使用 CGContextMoveToPoint 函數設置線的起點。
  4. 使用 CGContextAddLineToPoint 函數移動圖形環境的畫筆,來指定線的終點。
  5. 使用 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
接合點為圓角

效果如下圖所示:

圖5-1 core Graphics 的三種線的接合類型

為了完成這個,我寫了一個名為drawRooftopAtTopPointof:text ToDisplay:lineJoin:的方 法,它接受三個參數:

  1. 一個點,屋頂的頂部在這一點
  2. 屋頂內顯示的文字
  3. 要使用的接合類型

下面是代碼:

- (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 參數,代表了在給定路徑上繪制形狀和線時可能用到的變換.

圖6-1 使用路徑在圖形環境上繪圖

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);
}

這里在路徑上畫了一個矩形,用矢車菊藍填充它,并用棕色描出了矩形的邊緣。

圖7-1用路徑繪制矩形

如果你有多個矩形要繪制,你可以向 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 過程的參數有:

  1. 要添加矩形的路徑句柄
  2. 變換,如果有的話,應用到矩形上。
  3. CGRect 數組的引用
  4. 前一個參數中數組的大小。你傳入的這個參數一定要和矩形數相等,以避免此過程出 現未知的行為。
圖 7-2 一次繪制多個矩形
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,443評論 6 532
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,530評論 3 416
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,407評論 0 375
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,981評論 1 312
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,759評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,204評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,263評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,415評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,955評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,782評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,983評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,528評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,222評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,650評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,892評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,675評論 3 392
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,967評論 2 374

推薦閱讀更多精彩內容

  • 最近在看《iOS 6 Programming Cookbook》的翻譯版,它由DevDiv論壇的網友翻譯,原文地址...
    0o凍僵的企鵝o0閱讀 889評論 0 0
  • Core Graphics Framework是一套基于C的API框架,使用了Quartz作為繪圖引擎。它提供了低...
    ShanJiJi閱讀 1,550評論 0 20
  • 最近在看《iOS 6 Programming Cookbook》的翻譯版,它由DevDiv論壇的網友翻譯,原文地址...
    0o凍僵的企鵝o0閱讀 435評論 0 1
  • 一碗濃濃的豆腐鯽魚湯讓冬日里溫暖起來,自制肉皮凍健康又美味,還有最愛的大救駕,家鄉的味道,完美晚餐,我這個廚子當的...
    nomoi閱讀 181評論 0 0
  • 你,有沒有過這樣的時候? 莫名地心情不好,不想和任何人說話,只想一個人靜靜地發呆,懷念著逝去的人和事。 你,有沒有...
    文文心兒閱讀 275評論 2 13