CoreGraphics核心圖形框架相較於UIKit框架更加偏於底層。在Objective-C工程中,CoreGraphics其中方法都是採用C語言風格進行編寫的,同時其並不支持Objective-C的自動引用計數,在使用這個框架進行編程時,開發者要手動對內存進行管理。在Swift工程中,Apple使用Swift語言對CoreGraphics礦建進行了重構,將CGPath,CGMutablePaht等都從新定義爲了類。CGPath能夠理解爲圖形的路徑,在Objective-C工程中,其實系統定義的一個內部結構體,開發者不能夠直接使用,開發者CGPathRef和CGMutablePathRef別名做爲CGPath的引用,實際上,CGPathRef和CGMutablePathRef都是CGPath結構體類型的指針,不一樣的是一個是const類型不可修改的,一個是能夠修改的,系統定義以下:編程
typedef struct CGPath *CGMutablePathRef; typedef const struct CGPath *CGPathRef;
關於CGPath的建立與內存管理的相關方法,列舉以下:數組
//這個方法獲取CGPath類在CoreGraphics框架中的惟一標識 //CFTypeID 其實是無符號整型的別名 其爲CoreGraphics框架中每一個類都定義了一個標識 CGPath爲280 CFTypeID CGPathGetTypeID(void); //這個方法建立一個srtuct CGPath * 指針 能夠理解爲可變的CGPath類 CGMutablePathRef CGPathCreateMutable(void); //這個方法經過一個CGPathRef來建立CGPathRef CGPathRef CGPathCreateCopy(CGPathRef path); //這個方法在經過CGPathRef建立CGPathRef時會將得路徑進行transform變換後返回 CGPathRef CGPathCreateCopyByTransformingPath(CGPathRef path, const CGAffineTransform * transform); //這個方法經過CGPathRef建立可變的CGMutablePathRef CGMutablePathRef CGPathCreateMutableCopy(CGPathRef path); //意義同上,在建立的CGMutablePathRef基礎上進行一次transform變換在返回 CGMutablePathRef CGPathCreateMutableCopyByTransformingPath(CGPathRef path, const CGAffineTransform * transform) //這個方法將建立矩形路徑 第一個參數爲要繪製的矩形區域 第2個參數爲要進行的transform變換 CGPathRef CGPathCreateWithRect(CGRect rect,const CGAffineTransform * transform); //這個方法將建立橢圓形路徑 CGPathRef CGPathCreateWithEllipseInRect(CGRect rect, const CGAffineTransform * transform); //這個方法用於建立圓角矩形路徑 /* rect :繪製的矩形區域 cornerWidth: 橫向圓角尺寸 cornerHeight:縱向圓角尺寸 */ CGPathRef CGPathCreateWithRoundedRect(CGRect rect, CGFloat cornerWidth, CGFloat cornerHeight,const CGAffineTransform * transform); //這個方法用於建立虛線路徑 /* 這個方法略微有些複雜 其中參數意義以下: path:要進行虛線化的路徑 phase:從lengths數組的第幾部分開始繪製虛線 lengths:C風格的數組 其中爲CGFloat值 表示每段虛線的繪製長度 例如傳入數組爲{10,5},則虛線的先繪製長度爲10的實線 在繪製長度爲5的空白 在進行循環 count:這個參數須要設置爲lengths數組的長度 */ CGPathRef CGPathCreateCopyByDashingPath(CGPathRef path, const CGAffineTransform * transform,CGFloat phase, const CGFloat *lengths, size_t count); //經過CGPathRef來建立斜線 /* lineWidth:設置線寬 lineCap:設置線帽風格 可選參數以下: typedef CF_ENUM(int32_t, CGLineCap) { kCGLineCapButt, 默認的風格 線的端點精確到點 kCGLineCapRound, 圓滑的端點 線的端點爲半徑爲線寬一半的圓弧 kCGLineCapSquare 尖銳的過渡 }; lineJoin:設置鏈接線處的風格 可選參數以下: typedef CF_ENUM(int32_t, CGLineJoin) { kCGLineJoinMiter, //以鋒利的角做爲鏈接線的轉折 kCGLineJoinRound, //以圓角做爲鏈接線的轉折 kCGLineJoinBevel //貝塞爾風格的轉折 }; miterLimit:這個值將決定線鏈接處角的鋒利程度 */ CGPathRef CGPathCreateCopyByStrokingPath(CGPathRef cg_nullable path, const CGAffineTransform * __nullable transform,CGFloat lineWidth, CGLineCap lineCap,CGLineJoin lineJoin, CGFloat miterLimit); //手動使CGPathRef引用計數+1 CGPathRef CGPathRetain(CGPathRef cg_nullable path); //手動使CGPathRef引用計數-1 void CGPathRelease(CGPathRef cg_nullable path);
自定義一個View視圖,在其drawRect方法中進行界面的繪製,示例代碼以下:框架
- (void)drawRect:(CGRect)rect { //獲取當前繪圖上下文 CGContextRef contextRef = UIGraphicsGetCurrentContext(); CGPoint center = CGPointMake(rect.size.width/2, rect.size.height/2); //建立圓角矩形路徑 CGPathRef pathRef = CGPathCreateWithRoundedRect(CGRectMake(center.x-50, center.y-50, 100, 100), 30, 10, nil); //將路徑虛線化 CGFloat floats[] = {10,5}; pathRef = CGPathCreateCopyByDashingPath(pathRef, nil, 0, floats, 2); //設置繪製顏色 [[UIColor redColor] setStroke]; //將路徑添加到繪圖上下文中 CGContextAddPath(contextRef, pathRef); //進行繪製 CGContextDrawPath(contextRef, kCGPathStroke); //內存釋放 CGPathRelease(pathRef); }
運行後效果以下圖所示:函數
//將路徑移動到一個點做爲起點 void CGPathMoveToPoint(CGMutablePathRef path,const CGAffineTransform * m, CGFloat x, CGFloat y); //將路徑移動到某個點畫出一條線 void CGPathAddLineToPoint(CGMutablePathRef path,const CGAffineTransform * m, CGFloat x, CGFloat y); //向路徑中添加一段二次貝塞爾曲線 /* cpx:控制點的x座標 cpy:控制點的y座標 */ void CGPathAddQuadCurveToPoint(CGMutablePathRef path,const CGAffineTransform * m, CGFloat cpx, CGFloat cpy,CGFloat x, CGFloat y); //添加一段三次貝塞爾曲線 void CGPathAddCurveToPoint(CGMutablePathRef path,const CGAffineTransform * m, CGFloat cp1x, CGFloat cp1y,CGFloat cp2x, CGFloat cp2y, CGFloat x, CGFloat y); //這個方法用於閉合路徑 調用這個方法後 路徑最後的端點將和起點閉合 void CGPathCloseSubpath(CGMutablePathRef path); //向路徑中追加一個矩形 void CGPathAddRect(CGMutablePathRef path, const CGAffineTransform * m, CGRect rect); //向路徑中追加一組矩形 void CGPathAddRects(CGMutablePathRef path, const CGAffineTransform * m, const CGRect * rects,size_t count); //向路徑中追加一組線條 void CGPathAddLines(CGMutablePathRef path, const CGAffineTransform * m, const CGPoint * __nullable points, size_t count); //添加一組橢圓 void CGPathAddEllipseInRect(CGMutablePathRef cg_nullable path,const CGAffineTransform * m, CGRect rect); //向路徑中追加一組圓弧 /* x:圓心x座標 y:圓心y座標 radius:弧線半徑 startAngle:起始角度 endAngle:終止角度 clockwise:是否順時針繪製 */ void CGPathAddArc(CGMutablePathRef path, const CGAffineTransform * m, CGFloat x, CGFloat y, CGFloat radius, CGFloat startAngle, CGFloat endAngle, bool clockwise); //向路徑中追加一組圓弧 /* x:圓心x座標 y:圓心y座標 radius:弧線半徑 startAngle:起始角度 delta:圓弧繪製的長度 爲弧度制 2π爲整個圓 */ void CGPathAddRelativeArc(CGMutablePathRef path, const CGAffineTransform * __nullable matrix, CGFloat x, CGFloat y, CGFloat radius, CGFloat startAngle, CGFloat delta); //向路徑中追加一段圓弧 弧線是以(x1,y1)到(x2,y2)爲切線的弧線 void CGPathAddArcToPoint(CGMutablePathRef path,const CGAffineTransform * m, CGFloat x1, CGFloat y1, CGFloat x2, CGFloat y2, CGFloat radius); //向路徑中追加一段路徑 void CGPathAddPath(CGMutablePathRef path1,const CGAffineTransform * m, CGPathRef path2);
示例代碼以下:spa
- (void)drawRect:(CGRect)rect { CGContextRef contextRef = UIGraphicsGetCurrentContext(); CGPoint center = CGPointMake(rect.size.width/2, rect.size.height/2); CGMutablePathRef pathRef = CGPathCreateMutable(); CGPathMoveToPoint(pathRef, nil, center.x, center.y-50); CGPathAddLineToPoint(pathRef, nil, center.x+100, center.y); CGPathAddQuadCurveToPoint(pathRef, nil, 0, 0, center.x+100, center.y-100); CGPathAddRelativeArc(pathRef, nil, 100, 100, 50, 0, M_PI); CGPathCloseSubpath(pathRef); [[UIColor redColor] setStroke]; CGContextAddPath(contextRef, pathRef); CGContextDrawPath(contextRef, kCGPathStroke); CGPathRelease(pathRef); CGContextRelease(contextRef); }
效果以下圖所示:指針
//判斷某個路徑是否爲空 bool CGPathIsEmpty(CGPathRef path); //判斷某個路徑是否爲某個矩形 bool CGPathIsRect(CGPathRef cg_nullable path, CGRect * rect); //獲取某個路徑當前繪製所在的點 CGPoint CGPathGetCurrentPoint(CGPathRef path); //獲取某個路徑包含全部點的尺寸 CGPathGetBoundingBox(CGPathRef cg_nullable path); //獲取某個路徑的尺寸 CGRect CGPathGetPathBoundingBox(CGPathRef path); //判斷路徑是否包含某個點 bool CGPathContainsPoint(CGPathRef path, const CGAffineTransform * m, CGPoint point, bool eoFill);
當每次向CGPath路徑作操做時,操做的過程實際上都會被記錄下來,每一個操做行爲節點都被封裝爲了CGPathElement結構體,開發者能夠經過以下方法來獲取全部操做行爲:code
CGPathApply(pathRef, nil, func);
CGPathApply()方法中的第3個參數爲一個函數指針,示例C函數實現以下:orm
void func(void * __nullable info, const CGPathElement * element){ printf("%d",(*element).type); }
CGPathElement結構體的定義以下:ip
struct CGPathElement { //操做節點的類型 CGPathElementType type; //對應的點集 CGPoint * points; }; //CGPathElementType枚舉定義以下 typedef CF_ENUM(int32_t, CGPathElementType) { //移動到點的操做行爲 kCGPathElementMoveToPoint, //添加線的操做行爲 kCGPathElementAddLineToPoint, //添加二次貝塞爾曲線的操做行爲 kCGPathElementAddQuadCurveToPoint, //添加三次貝塞爾曲線的操做行爲 kCGPathElementAddCurveToPoint, //閉合路徑的操做行爲 kCGPathElementCloseSubpath };
專一技術,熱愛生活,交流技術,也作朋友。內存
——琿少 QQ羣:203317592