利用UIView上手勢控制OpenGL的繪製

場景

獲取IOS設備上相冊裏的圖片,在平移/縮放/旋轉等編輯操做後,調用內核繪製圖片,保證視覺上其顯示效果(圖片位置和圖片內容)不改變:objective-c

  • 圖片編輯時,UIView接受手勢,用UIKit實時展示圖片的變換狀態;
  • 編輯完成時,將圖片和變換矩陣傳入內核,利用OpenGL繪製最終狀態。

問題

UIKitOpenGL的座標系不相同:網絡

  • UIKit的座標系:以左上角爲原點,X軸向右,Y軸向下(右圖);
  • OpenGL的座標系:以左下角爲原點,X軸向右,Y軸向上(左圖); 圖片來源於網絡

解決方案

圖片編輯過程當中,響應手勢並經過圖片的centertransform動態更新顯示;同時將全部圖片的變換累積到一個變換矩陣imageTransform中;在編輯完成時內核利用imageTransform將圖片正確繪製。須要注意的是:code

centertransformUIKit座標系,imageTransformOpenGL座標系。orm

1.初始化

在進入圖片編輯模塊時,初始化imageTransform圖片

self.imageTransform = CGAffineTransformIdentity;

2.平移

響應pan手勢。因爲兩個座標系的Y軸方向相反,因此imageTransform累積平移變換時,須要將Y軸方向變化量取反it

-(void)panImage:(UIPanGestureRecognizer*)pan {
	if (pan.state == UIGestureRecognizerStateChanged) {
  		/// 改變圖片顯示狀態
  		CGPoint loc = [pan translationInView:self.view];
  		[pan setTranslation:CGPointZero inView:self.view];
  		self.imageView.center = CGPointMake(self.imageView.center.x+loc.x, self.imageView.center.y+loc.y);

  		/// 累積平移矩陣
  		CGAffineTransform tX = CGAffineTransformIdentity;
  		tX = CGAffineTransformTranslate(tX, loc.x, -loc.y);
  		self.imageTransform = CGAffineTransformConcat(self.imageTransform, tX);
  	}
}

3.縮放

UIView的縮放默認是以其中心點爲固定點,因此imageTransform累積縮放變換時,須要先將圖片移動到原點位置,進行縮放後再恢復io

-(void)pinchImage:(UIPinchGestureRecognizer*)pinch{    
    if (pinch.state == UIGestureRecognizerStateChanged) {
		/// 改變圖片顯示狀態
        self.imageView.transform = CGAffineTransformScale(self.imageView.transform, pinch.scale, pinch.scale);
        	
    	/// 累積平移矩陣
    	CGPoint pivot = self.imageView.center;
        pivot.y = self.view.bounds.size.height - pivot.y;
        CGAffineTransform tX = CGAffineTransformIdentity; 
        tX = CGAffineTransformIdentity;
        tX = CGAffineTransformTranslate(tX, pivot.x, pivot.y);
        tX = CGAffineTransformScale(tX, pinch.scale, pinch.scale);
        tX = CGAffineTransformTranslate(tX, -pivot.x, -pivot.y)
        self.imageTransform = CGAffineTransformConcat(self.imageTransform, tX);
 
 		/// 充值縮放因子
        pinch.scale = 1;
    }
}

4.旋轉

在UIKit的座標系中,由X軸正方向朝Y軸正方向旋轉n弧度(視覺上是逆時針),至關於在OpenGL座標系中由X軸正方向朝Y軸正方向旋轉PI-n弧度(視覺上是順時針)。此時獲得的圖片只是旋轉角度正確了,最後還須要對圖片進行相對於圖片中心的翻轉才能獲得同樣的圖片內容。form

-(void)rotateImage:(UIRotationGestureRecognizer*)rotate{    
    if (rotate == UIGestureRecognizerStateChanged) {
        /// 改變圖片顯示狀態
        CGFloat angle = rotate.rotation;
        self.imageView.transform = CGAffineTransformRotate(self.imageView.transform, angle);
        
        /// 累積平移矩陣
        CGPoint pivot = self.imageView.center;
        pivot.y = self.view.bounds.size.height - pivot.y;
        CGAffineTransform tX = CGAffineTransformIdentity;
        tX = CGAffineTransformTranslate(tX, pivot.x, pivot.y);
        tX = CGAffineTransformRotate(tX, M_PI-angle);
        tX = CGAffineTransformScale(tX, -1, -1);	//中心翻轉
        tX = CGAffineTransformTranslate(tX, -pivot.x, -pivot.y);
        self.imageTransform = CGAffineTransformConcat(self.imageTransform, tX);
        
        // 重置旋轉角度
        rotate.rotation = 0;  
    }
}
相關文章
相關標籤/搜索