2011-07-28 3 views
3

私は、ユーザーが画像の一部を切り取ることができるアプリケーションを作成しています。これを行うために、UIBezierPathsを作成してクリッピングパスを形成します。現在の設定は次のとおりです。iOS:UIBezierPathから画像のクリッピングパスを作成する

  • UIImageViewは、切断しているイメージを表示します。
  • 上記のUIImageViewは、ユーザーが追加している UIBezierPathsを表示/更新するためのカスタムdrawRect:メソッドを が実行するUIImageViewのカスタムサブクラスです。
  • ユーザーが「完了」ボタンをクリックすると、保存されている配列をループしてappendPath:を呼び出すことで、ユーザーが作成したすべての個々のパスを組み込んだ新しいUIBezierPathオブジェクトが作成されます。この新しいUIBezierPathはパスを閉じます。

これまでのところ、私の知る限りです。私はUIBezierPathにaddClipメソッドがあることを知っていますが、ドキュメントから使用方法を理解することはできません。

一般に、私がクリッピングについて見たすべての例では、UIBezierPathラッパーではなくCore Graphicsを直接使用しています。私はUIBezierPathにCGPathプロパティがあることを認識しています。だから私は完全なUIBezierPathオブジェクトではなく、クリッピングの時にこれを使用する必要がありますか?

+1

クリップする部分をどのように検出していますか?ジェスチャーによる? – Shrawan

答えて

0

AppleはUIImageView class referenceに従って、UIImageViewをサブクラス化しないと言っています。これを指摘してくれてありがとうございます。

ただし、独自のdrawRectを実装する場合は、独自のUIViewサブクラスを使用してください。そしてdrawRectの中にはaddClipを使用しています。これをCGPathに変換せずにUIBezierPathで行うことができます。

- (void)drawRect:(CGRect)rect 
{ 
    // This assumes the clippingPath and image may be drawn in the current coordinate space. 
    [[self clippingPath] addClip]; 
    [[self image] drawAtPoint:CGPointZero]; 
} 

境界を埋めるためにスケールを拡大または縮小したい場合は、グラフィックスコンテキストを拡大縮小する必要があります。 (あなたが最初clippingPathをコピーする必要があると思いますので、またclippingPathへCGAffineTransformを適用することができ、それは永久的である。)

- (void)drawRect:(CGRect)rect 
{ 
    // This assumes the clippingPath and image are in the same coordinate space, and scales both to fill the view bounds. 
    if ([self image]) 
    { 
     CGSize imageSize = [[self image] size]; 
     CGRect bounds = [self bounds]; 

     CGContextRef context = UIGraphicsGetCurrentContext(); 
     CGContextScaleCTM(context, bounds.size.width/imageSize.width, bounds.size.height/imageSize.height); 

     [[self clippingPath] addClip]; 
     [[self image] drawAtPoint:CGPointZero]; 
    } 
} 

これは、各軸に個別に画像を拡大縮小します。アスペクト比を維持したい場合は、スケーリング全体を調整し、それを中央になるように変換するか、そうでなければ整列させる必要があります。

最終的には、パスが大きく描画された場合、これはすべて比較的遅いです。おそらく、CALayerに画像を保存する方が速く、パスが含まれているCAShapeLayerであるmaskであることがわかります。 のテスト以外の以下の方法は使用しないでください。イメージレイヤーとマスクを別々にスケーリングして整列させる必要があります。メリットは、下にあるイメージがレンダリングされることなくマスクを変更できることです。

- (void) setImage:(UIImage *)image; 
{ 
    // This method should also store the image for later retrieval. 
    // Putting an image directly into a CALayer will stretch the image to fill the layer. 
    [[self layer] setContents:(id) [image CGImage]]; 
} 

- (void) setClippingPath:(UIBezierPath *)clippingPath; 
{ 
    // This method should also store the clippingPath for later retrieval. 
    if (![[self layer] mask]) 
     [[self layer] setMask:[CAShapeLayer layer]]; 

    [(CAShapeLayer*) [[self layer] mask] setPath:[clippingPath CGPath]]; 
} 

レイヤーマスクを使用してイメージのクリッピングを行うと、drawRectメソッドが不要になります。効率のために取り外します。

関連する問題