Core Graphics圖形變換,coregraphics圖形
簡單的座標變換:
Quarzd 2D提供了三個API進行座標變換:
//1.位移變換CGContextTranslateCTM(CGContextRef c, CGFloat tx, CGFloat ty);
對於變換後的座標系而言,原點位於原座標系的(tx,ty)處。也相當於在原有座標系下,所有點的橫縱座標分別增加tx和ty。
//2.旋轉變換CGContextRotateCTM(CGContextRef c, CGFloat angle);
假設點A1經過座標變換變到了A2,記座標原點為O。則A1O = A2O(A2在以O為圓心,A1O長度為半徑的圓上)且∠A1OA2 = angel。這裡的旋轉是順時針旋轉。如果想用逆時針旋轉的話,使用-angel即可。
//3.縮放變換CGContextScaleCTM(CGContextRef c, CGFloat sx, CGFloat sy);
新座標系下所有點的橫縱座標等於原橫縱座標分別乘以縮放因子sx和sy。
需要注意的是:這裡的變換函數都是作用於上下文(context)的。但和前文所說修改繪圖設定不同的是,這些API修改了座標系統的狀態,即使調用CGContextDrawPath方法也無法恢複設定。
座標系統狀態的儲存與恢複
我們可以調用這一對方法來進行系統狀態的儲存和恢複。
CGContextSaveGState(CGContextRef c);//儲存當前繪圖狀態。CGContextRestoreGState(CGContextRef c);//恢複系統繪圖狀態。
一個繪圖上下文維護了一個繪圖系統狀態的棧。上下文被初始化時,這個棧為空白,所以先調用CGContextSaveGState方法,將當前系統狀態入棧,需要恢複時再調用CGContextRestoreGState出棧即可。這裡的“狀態”(State)不僅包含了當前座標系統的狀態,也包含了設定的填充風格、線條風格、陰影風格等各種狀態。需要切記的是,如果還沒有儲存狀態就調用了座標變換的API,那麼就再也無法恢複了。如果此時試圖調用CGContextRestoreGState方法,將會對一個空棧執行出棧方法,從而引起報錯。
*使用矩陣進行變換
Quartz 2D除了以上三個變換方法之外,還提供了更為一般的,利用矩陣處理座標變換的方法。
CGContextConcatCTM(CGContextRef c, CGAffineTransform transform);//Transform 是一個變換矩陣- (CGAffineTransform)CGContextGetCTM(CGContextRef c);//擷取當前上下文座標系的變換矩陣
變換矩陣CGAffineTransform transform可以這樣建立:
CGAffineTransform transform1 = CGAffineTransformMakeRotation(CGFloat angle);CGAffineTransform transform2 = CGAffineTransformMakeScale(CGFloat sx, CGFloat sy);CGAffineTransform transform3 = CGAffineTransformMakeTranslation(CGFloat tx, CGFloat ty);
這三個方法分別對應了旋轉變換、縮放變換和平移變換的API,因此就不做解釋了。
還可以建立一個更一般的變換矩陣:
CGAffineTransform transform = CGAffineTransformMake(CGFloat a, CGFloat b, CGFloat c, CGFloat d, CGFloat tx, CGFloat ty);
根據矩陣的運算規則和平移變換的變換規律,點A(x,y)經過transform矩陣作用後的點A’左邊應為(ax+cy+tx,bx+dy+ty)。
根據高中數學知識,得出常見的幾個變換矩陣:
CGAffineTransformMake(-1, 0, 0, 1, 0, 0);//關於X軸對稱變換CGAffineTransformMake(1, 0, 0, -1, 0, 0);//關於Y軸對稱變換CGAffineTransformMake(0, 1, 1, 0, 0, 0);//關於Y=X對稱變換CGAffineTransformMake(0, -1, -1, 0, 0, 0);//關於X軸對稱變換CGAffineTransformMake(1, 0, tan(α), 1, 0, 0);//水平傾斜α°角CGAffineTransformMake(1, -tan(α), 0, 1, 0, 0);//豎直傾斜α°角
還可以對已有的矩陣進行修改
CGAffineTransformScale(CGAffineTransform t, CGFloat sx, CGFloat sy);CGAffineTransformRotate(CGAffineTransform t, CGFloat angle);CGAffineTransformTranslate(CGAffineTransform t, CGFloat tx, CGFloat ty);//追加平移變換效果,上兩個方法類似CGAffineTransformInvert(CGAffineTransform t);//擷取一個變換矩陣的逆矩陣CGAffineTransformConcat(CGAffineTransform t1, CGAffineTransform t2);//拼接兩個變換矩陣,相當於t1左乘t2
變換矩陣不僅可以作用於內容相關的座標系,還可以作用於CGPoint、CGSize、CGRect等。不僅如此,UIView自身有一個transform屬性,支援設定變換矩陣,從而可以對UI控制項本身進行座標變換。
CGPoint newPoint = CGPointApplyAffineTransform(CGPoint point, CGAffineTransform t);CGSize newSize = CGSizeApplyAffineTransform(CGSize size, CGAffineTransform t);CGRect newRect = CGRectApplyAffineTransform(CGRect rect, CGAffineTransform t);