亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

iOS繪畫學習(3)

2019-11-14 20:16:51
字體:
來源:轉載
供稿:網友

Graphics Context Settings (圖形上下文設置)

一個圖形上下文狀態有很多個圖形上下文設置構成,這個狀態決定了在這個時刻繪畫的行為和外觀。下面列舉了Core Graphics 函數,同時跟著對應的UIKit 提供的封裝好的方便的方法:

  • 線的粗細和虛線樣式

    CGContextSetLineWidth, CGContextSetLineDash (and UIBezierPath lineWidth, setLineDash:count:phase:)

  • 線末端樣式和連接樣式

    CGContextSetLineCap, CGContextSetLineJoin, CGContextSetMiterLimit (and UIBezierPath lineCapStyle, lineJoinStyle, miterLimit)

  • 線顏色和模式

    CGContextSetRGBStrokeColor, CGContextSetGrayStrokeColor, CGContextSet- StrokeColorWithColor, CGContextSetStrokePattern (and UIColor setStroke)

  • 填充顏色和模式

    CGContextSetRGBFillColor, CGContextSetGrayFillColor, CGContextSetFill- ColorWithColor, CGContextSetFillPattern (and UIColor setFill)

  • 陰影

    CGContextSetShadow, CGContextSetShadowWithColor

  • 整體透明度和組合

    CGContextSetAlpha, CGContextSetBlendMode

  • 反鋸齒

    CGContextSetShouldAntialias

  • 其它額外的設置

    • 裁剪區域

      在裁剪區域外進行繪制,其實不會真的被繪制

    • 轉換(或者“CTM”,當前轉換矩陣)

      可以改變你指定的點在隨后的繪制命令中,如何對應到畫布的實際空間上。


Paths and Shapes (路徑和形狀)

下面是一些可能會用到的路徑繪制命令:

  • 當前點的位置

    CGContextMoveToPoint

  • 描摹一條線

    CGContextAddLineToPoint, CGContextAddLines

  • 描摹一個矩形

    CGContextAddRect, CGContextAddRects

  • 描摹一個橢圓或者圓形

    CGContextAddEllipseInRect

  • 描摹一個圓弧

    CGContextAddArcToPoint, CGContextAddArc

  • 描摹有一個或者兩個控制點的貝塞爾曲線

    CGContextAddQuadCurveToPoint, CGContextAddCurveToPoint

  • 關閉當前路徑

    CGContextClosePath 這個會在路徑的最后一個點和第一個點之間添加一條線,如果你是打算要填充這個路徑,那么不需要調用這個方法,填充操作會自動幫我們完成。

  • 描邊或者填充當前路徑

    CGContextStrokePath, CGContextFillPath, CGContextEOFillPath, CGContext- DrawPath. 描邊或者填充操作都會清除這個路徑。如果你想既描邊又填充路徑,可以使用CGContextDrawPath。 如果你僅僅先通過 CGContextStrokePath 描邊,你就不可能再填充這個路徑了,因為這個路徑已經被清除了。

    當然還有很多其它更方便的函數來創建一個路徑,然后描邊或者填充:CGContextStrokeLineSegments, CGContextStrokeRect, CGContextStrokeRectWithWidth, CGContextFillRect, CGContextFillRects, CGContextStrokeEllipseInRect, CGContextFillEllipseInRect.

一個路徑可以是混合而成的,意味著這個路徑由多個獨立的塊組成。例如,一個路徑可以包括兩個分開的閉合的形狀:一個矩形和一個圓形。 當你在構造一個路徑的某個時刻(也就是在描摹出一個路徑之后,同時沒有描邊,填充來清除路徑,或者調用 CGContextBeginPath)調用 CGContextMoveToPoint,你提起畫筆,然后移動到一個新的位置,接著準備開始一個獨立的一塊同樣的路徑。如果你擔心之前繪制的路徑會被清除,可以調用CGContextBeginPath 來指定你開始一段新的不同的路徑,在蘋果的很多例子中都會這么做,但是我在實際中通常發現不需要。

為了說明上面路徑繪制的命令,我會生成一個向上的箭頭,如下圖所示。這可能不是創建一個箭頭的最好方式,同時我也會故意不使用一個方便的函數,但是過程是清晰的:

// obtain the current graphics contextCGContextRef con = UIGraphicsGetCurrentContext();// draw a black (by default) vertical line, the shaft of the arrowCGContextMoveToPoint(con, 100, 100);CGContextAddLineToPoint(con, 100, 19);CGContextSetLineWidth(con, 20);CGContextStrokePath(con);// draw a red triangle, the point of the arrowCGContextSetFillColorWithColor(con, [[UIColor redColor] CGColor]);CGContextMoveToPoint(con, 80, 25);CGContextAddLineToPoint(con, 100, 0);CGContextAddLineToPoint(con, 120, 25);CGContextFillPath(con);// snip a triangle out of the shaft by drawing in Clear blend modeCGContextMoveToPoint(con, 90, 101);CGContextAddLineToPoint(con, 100, 90);CGContextAddLineToPoint(con, 110, 101);CGContextSetBlendMode(con, kCGBlendModeClear);CGContextFillPath(con);

如果你想復用或者分享一個路徑,可以把這個路徑包裝成 CGPath,實際上就是CGPathRef。你也可以創建一個新的CGMutablePathRef ,像CGContext 中的路徑構造方法一樣,使用不同的CGPath 方法來構造路徑,或者你可以使用CGContextCopyPath 來復制圖形上下文中當前的路徑。還有一些CGPath方法用來基于簡單的幾何圖形來創建一個路徑(CGPathCreateWithRect, CGPathCreateWithEllipseInRect)或者基于一個已存在的路徑(CGPathCreateCopyByStrokingPath, CGPathCreateCopyByDashing- Path, CGPathCreateCopyByTransformingPath)。

UIKit 中的UIBezierPath封裝了CGPath,同樣也提供了一些路徑構造方法,例如 moveToPoint:, addLineToPoint:, bezierPathWithRect:, bezierPathWithOvalInRect:, addArcWithCenter:radius:startAngle:endAngle:clockwise:, addQuadCurveToPoint:controlPoint:, addCurveToPoint:controlPoint1:controlPoint2:, closePath。同樣,UIBezierPath也提供了一個非常有用的方法:bezierPathWithRoundedRect:cornerRadius: —— 僅僅使用Core Graphics 方法來繪制圓角矩形是非常繁瑣的。當你調用UIBezierPath 實例方法 fill 或者 stroke (或者 fillWithBlendMode:alpha: 或者 strokeWithBlend- Mode:alpha:)時,當前圖形上下文狀態會被保存,被封裝好的CGPath 路徑會變成當前上下文的繪制路徑,然后描邊或者填充該路徑,最后當前上下文會被恢復原來狀態。

下面我們使用UIKit 提供的UIBezierPath 來重寫上面的箭頭:

UIBezierPath* p = [UIBezierPath bezierPath];[p moveToPoint:CGPointMake(100,100)];[p addLineToPoint:CGPointMake(100, 19)];[p setLineWidth:20];[p stroke];[[UIColor redColor] set];[p removeAllPoints];[p moveToPoint:CGPointMake(80,25)];[p addLineToPoint:CGPointMake(100, 0)];[p addLineToPoint:CGPointMake(120, 25)];[p fill];[p removeAllPoints];[p moveToPoint:CGPointMake(90,101)];[p addLineToPoint:CGPointMake(100, 90)];[p addLineToPoint:CGPointMake(110, 101)];[p fillWithBlendMode:kCGBlendModeClear alpha:1.0];

Clipping (裁剪)

路徑的另一種使用方式是遮罩某一塊區域,防止在未來的繪制中被改變。這種就是裁剪。默認,一個圖形上下文的裁剪區域就是整一個圖形上下文,你可以在上下文中任意繪制。

裁剪區域是整個上下文的一個功能,任何新的裁剪區域會被應用到現有的裁剪區域,相交而成。如果你應用了自己的裁剪區域,在后面想移除這個裁剪區域的辦法就只能把你的處理包含在 CGContextSaveGState和CGContextRestoreGState方法之間。

為了說明這一點,我將使用裁剪重寫生成我們原來的箭頭符號,而不是使用混合模式在箭頭尾部“切出”三角缺口。這樣會有些棘手,因為我們想要的不是裁剪三角形內部的區域,而是外面的區域。為了解析這個,我們使用包含超過一個閉合區域的混合路徑 —— 一個三角形,以及整個繪制區域(我們可以使用CGContextGetClipBoundingBox 獲?。?/p>

當填充一個混合路徑時,或者使用路徑來表示一個裁剪區域時,系統遵循兩個準則:

  • 非零環繞數規則(Winding rule)

    環繞(winding)就是一個路徑環繞的方向,分順時針(正方向)和逆時針(負方向)。在圖形學中判斷一個點是否在多邊形內,若多邊形不是自相交的,那么可以簡單的判斷這個點在多邊形內部還是外部;若多邊形是自相交的,那么就需要根據非零環繞數規則和奇-偶規則判斷。這里推薦一篇文章:http://blog.csdn.net/freshforiphone/article/details/8273023。

  • 奇-偶規則(Odd-even Rule)

    從任意位置p作一條射線,若與該射線相交的多邊形邊的數目為奇數,則p是多邊形內部點,否則是外部點。

這里我們使用簡單的奇-偶規則,所以我們使用CGContextEOClip 來設定裁剪區域,然后繪制箭頭:

// obtain the current graphics contextCGContextRef con = UIGraphicsGetCurrentContext();// punch triangular hole in context clipping regionCGContextMoveToPoint(con, 90, 100);CGContextAddLineToPoint(con, 100, 90);CGContextAddLineToPoint(con, 110, 100);CGContextClosePath(con);CGContextAddRect(con, CGContextGetClipBoundingBox(con));CGContextEOClip(con);// draw the vertical lineCGContextMoveToPoint(con, 100, 100);CGContextAddLineToPoint(con, 100, 19);CGContextSetLineWidth(con, 20);CGContextStrokePath(con);// draw the red triangle, the point of the arrowCGContextSetFillColorWithColor(con, [[UIColor redColor] CGColor]);CGContextMoveToPoint(con, 80, 25);CGContextAddLineToPoint(con, 100, 0);CGContextAddLineToPoint(con, 120, 25);CGContextFillPath(con);

UIBezierPath 的裁剪命令是 usesEvenOddFillRule 和 addClip。


Gradients (漸變)

漸變可以很簡單,也可以很負責,這里只講解簡單的。一個簡單的漸變是由一個起始點的顏色和一個結束點的顏色,再加上(可選的)一個中間點的顏色值決定,然后就會在上下文中在兩個指定的點以線性或者反射形式繪制。

你不能使用漸變來作為路徑的填充顏色,但是你可以使用裁剪來規定一個路徑形狀的漸變。為了說明這一點,我會重畫我們的箭頭,使用一個線性漸變:

// obtain the current graphics contextCGContextRef con = UIGraphicsGetCurrentContext();CGContextSaveGState(con);// punch triangular hole in context clipping regionCGContextMoveToPoint(con, 90, 100);CGContextAddLineToPoint(con, 100, 90);CGContextAddLineToPoint(con, 110, 100);CGContextClosePath(con);CGContextAddRect(con, CGContextGetClipBoundingBox(con));CGContextEOClip(con);// draw the vertical line, add its shape to the clipping regionCGContextMoveToPoint(con, 100, 100);CGContextAddLineToPoint(con, 100, 19);CGContextSetLineWidth(con, 20);CGContextReplacePathWithStrokedPath(con);CGContextClip(con);// draw the gradientCGFloat locs[3] = { 0.0, 0.5, 1.0 };CGFloat colors[12] = {    0.3,0.3,0.3,0.8, // starting color, transparent gray    0.0,0.0,0.0,1.0, // intermediate color, black    0.3,0.3,0.3,0.8 // ending color, transparent gray};CGColorSpaceRef sp = CGColorSpaceCreateDeviceGray();CGGradientRef grad =    CGGradientCreateWithColorComponents (sp, colors, locs, 3);CGContextDrawLinearGradient (    con, grad, CGPointMake(89,0), CGPointMake(111,0), 0);CGColorSpaceRelease(sp);CGGradientRelease(grad);CGContextRestoreGState(con); // done clipping// draw the red triangle, the point of the arrowCGContextSetFillColorWithColor(con, [[UIColor redColor] CGColor]);CGContextMoveToPoint(con, 80, 25);CGContextAddLineToPoint(con, 100, 0);CGContextAddLineToPoint(con, 120, 25);CGContextFillPath(con);

調用CGContextReplacePathWithStrokedPath 這個方法來防止描邊當前的路徑。


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
海角国产乱辈乱精品视频| 国产精品视频免费在线| 国产亚洲精品美女久久久久| 日韩免费视频在线观看| 欧美激情网站在线观看| 91国在线精品国内播放| 97av在线视频免费播放| 清纯唯美日韩制服另类| 欧洲亚洲免费视频| 亚洲一区二区精品| 日韩av最新在线| 亚洲高清免费观看高清完整版| 欧美成人激情在线| 91国内在线视频| 色悠悠久久久久| 欧美日韩亚洲高清| 国产精品三级美女白浆呻吟| 欧美激情精品久久久久久变态| 国产精品视频一区二区三区四| 欧美日韩激情视频| 国产成人涩涩涩视频在线观看| 精品免费在线观看| 精品国产乱码久久久久久天美| 欧美日韩免费区域视频在线观看| 欧美成年人视频网站| 国产欧美精品日韩精品| 日韩电影大全免费观看2023年上| 在线成人激情黄色| 欧美精品久久一区二区| 欧洲亚洲在线视频| 日韩免费在线看| 欧美日韩国产综合新一区| 一区二区三区天堂av| 亚洲精品日产aⅴ| 国产91在线视频| 成人午夜小视频| 久久亚洲精品成人| 91亚洲一区精品| 亚洲精品视频免费在线观看| 亚洲一区二区中文字幕| 国产精品极品美女粉嫩高清在线| 欧美一二三视频| 国产噜噜噜噜噜久久久久久久久| 亚洲白虎美女被爆操| 日本精品久久久久久久| 日韩精品欧美激情| 中文字幕av一区中文字幕天堂| 2019中文字幕免费视频| 日韩69视频在线观看| 91久久国产婷婷一区二区| 国产精品久久久久7777婷婷| 日韩网站在线观看| 超碰精品一区二区三区乱码| 国产精品吊钟奶在线| 国产成人精品最新| 久久精品国产v日韩v亚洲| 欧美高清videos高潮hd| 日韩精品丝袜在线| 亚洲精品久久久久中文字幕二区| 国产91亚洲精品| 亚洲视频777| 成人国产在线视频| 成人黄色网免费| 久久综合88中文色鬼| 欧美裸体xxxx极品少妇软件| 日韩欧美亚洲一二三区| 国产亚洲激情在线| 青草青草久热精品视频在线观看| 视频一区视频二区国产精品| 色噜噜久久综合伊人一本| 最近日韩中文字幕中文| 91在线观看免费观看| 国产精品99久久99久久久二8| 国产成人激情视频| 91免费精品视频| 亚洲а∨天堂久久精品9966| 91av在线播放视频| 91精品视频在线| 久久精品国产一区二区三区| 亚洲色图av在线| 国产视频精品一区二区三区| 97国产在线观看| 国产欧美日韩免费看aⅴ视频| 精品亚洲一区二区| 亚洲视屏在线播放| 日韩专区在线播放| 精品视频在线播放色网色视频| 国产亚洲精品久久| 亚洲男人天堂手机在线| 亚洲自拍偷拍网址| 成人天堂噜噜噜| 97久久国产精品| 久久久久久91香蕉国产| 欧美日韩国产一中文字不卡| 国产亚洲福利一区| 狠狠色狠色综合曰曰| 日韩中文字幕视频| 亚洲国产另类 国产精品国产免费| 欧美日本高清视频| 亚洲午夜精品久久久久久久久久久久| 日本精品视频网站| 成人午夜激情网| 国产女精品视频网站免费| 国内精品久久久久伊人av| 亚洲a在线观看| 欧美亚洲在线视频| 国产精品白丝jk喷水视频一区| 91精品国产高清久久久久久久久| 亚洲欧洲一区二区三区久久| 热久久这里只有精品| 国产视频精品一区二区三区| 国产精品观看在线亚洲人成网| 日韩av网址在线| 日韩精品中文字幕在线播放| 亚洲高清av在线| 亚洲第一天堂无码专区| 69av在线播放| 亚洲自拍偷拍第一页| 亚洲精品网站在线播放gif| 精品国产拍在线观看| 欧美亚洲国产日韩2020| 亚洲欧美国产日韩中文字幕| 色噜噜国产精品视频一区二区| 26uuu亚洲国产精品| 欧美日韩一区二区精品| 欧美国产视频一区二区| 91禁国产网站| 疯狂欧美牲乱大交777| 国产97在线|亚洲| 久久久久久国产精品美女| 亚洲一区二区三区视频播放| 成人网欧美在线视频| 国产福利精品av综合导导航| 亚洲欧美国产精品专区久久| 成人两性免费视频| 日韩欧美亚洲综合| 国产精品爱久久久久久久| 亚洲欧洲日韩国产| 97精品免费视频| 91久久精品美女高潮| 色悠悠久久88| 成人黄色大片在线免费观看| 国产成人精彩在线视频九色| 欧美日本在线视频中文字字幕| 国产一区二区三区三区在线观看| 中文字幕欧美专区| 日本国产一区二区三区| 国产精品美女在线观看| 欧美国产在线视频| 亚洲精品视频久久| 亚洲欧美在线一区| 亚洲视频日韩精品| 亚洲精品一区二区三区不| 亚洲色图美腿丝袜| 国产精品国产三级国产专播精品人| 欧美一级视频一区二区| 欧美精品制服第一页| 国产精品91免费在线| 中日韩午夜理伦电影免费| 最近2019中文字幕大全第二页| 亚洲韩国青草视频| 欧美日韩亚洲激情| 亚洲香蕉成人av网站在线观看| 亚洲欧美日韩另类|