2014-01-09 54 views
3

我有一個應用程序,用戶可以在一個加載的圖像上自由繪製。他選擇一種鉛筆顏色,並開始繪製圖像。Xamarin iOS - 縮放後繪製圖像

除此之外,他還可以通過手指縮放圖像,這就是我遇到問題的地方。

縮放後,繪製到圖像時,它變得模糊,奇怪收縮..

代碼縮放:

void ScaleImage (UIPinchGestureRecognizer gestureRecognizer) 
     { 
      AdjustAnchorPoint (gestureRecognizer); 
      if (gestureRecognizer.State == UIGestureRecognizerState.Began || gestureRecognizer.State == UIGestureRecognizerState.Changed) { 
       gestureRecognizer.View.Transform *= CGAffineTransform.MakeScale (gestureRecognizer.Scale, gestureRecognizer.Scale); 
       gestureRecognizer.Scale = 1; 
      } 
     } 

代碼繪製:

public override void TouchesBegan (NSSet touches, UIEvent evt) 
      { 
       base.TouchesBegan (touches, evt); 

       if (!canDraw) 
        return; 

       UITouch touch = (UITouch)touches.AnyObject; 
       lastPoint = touch.LocationInView (MyImageView); 
      } 

public override void TouchesMoved (NSSet touches, UIEvent evt) 
     { 
      base.TouchesMoved (touches, evt); 

      if (!canDraw) 
       return; 

      UITouch touch  = (UITouch)touches.AnyObject; 
      PointF currentPoint = touch.LocationInView (MyImageView); 

      UIGraphics.BeginImageContext (MyImageView.Frame.Size); 

      MyImageView.Image.Draw (new RectangleF (
       0, 0, 
       MyImageView.Frame.Size.Width, 
       MyImageView.Frame.Size.Height)); 

      CGContext ctx = UIGraphics.GetCurrentContext(); 
      ctx.SetLineCap (CGLineCap.Round); 
      ctx.SetLineWidth (5.0f); 
      ctx.SetRGBStrokeColor (red, green, blue, 1); 

      CGPath path = new CGPath(); 
      path.MoveToPoint(MyImageView.Transform, lastPoint.X, lastPoint.Y); 
      path.AddLineToPoint (MyImageView.Transform, currentPoint.X, currentPoint.Y); 
      ctx.AddPath (path); 
      ctx.DrawPath (CGPathDrawingMode.Stroke); 

      MyImageView.Image = UIGraphics.GetImageFromCurrentImageContext(); 
      UIGraphics.EndImageContext(); 

      lastPoint = currentPoint; 
     } 

在此先感謝!

回答

3

我通過使用Bezier Paths而不是Core Graphics來實現它。

您可以找到有關貝塞爾路徑的一些背景這裏: https://developer.apple.com/library/ios/documentation/2ddrawing/conceptual/drawingprintingios/BezierPaths/BezierPaths.html

因爲我想實現一個撤銷按鈕,我創建了一個類用於存儲顏色的線,以及相應的路徑:

public class VESLine{ 
public UIBezierPath Path { 
    get; 
    set; 
} 

public UIColor Color { 
    get; 
    set; 
} 

public byte Index { 
    get; 
    set; 
} 
} 

TouchesBegan事件被相應地修改,以創建新的UIBezierPath對象,其存儲在陣列中與它的顏色和索引,並且觸摸位置沿着:

public override void TouchesBegan (MonoTouch.Foundation.NSSet touches, UIEvent evt) 
{ 
    IndexCount++; 

    UIBezierPath path = new UIBezierPath(); 
    path.LineWidth  = 5.0f; 

    UITouch touch = (UITouch)touches.AnyObject; 
    previousPoint1 = touch.PreviousLocationInView (this); 

    PointF p = touch.LocationInView (this); 
    path.MoveTo (p); 

    InvokeOnMainThread (() => { 
     this.SetNeedsDisplay(); 
    }); 

    currentPath = path; 

    VESLine line = new VESLine() { 
     Path = currentPath, 
     Color = StrokeColor, 
     Index = IndexCount 
    }; 
    lines.Add(line); 
} 

TouchesMoved通過使用QuadCurve而不是常規線,還修改了事件以創建平滑線路徑。我還調用SetNeedsDisplay方法,以迫使視圖附圖中:

public override void TouchesMoved (MonoTouch.Foundation.NSSet touches, UIEvent evt) 
{ 
    UITouch touch = (UITouch)touches.AnyObject; 
    PointF p  = touch.LocationInView (this); 

    if (Math.Abs (p.X - previousPoint1.X) >= 4 || 
     Math.Abs (p.Y - previousPoint1.Y) >= 4) { 

     PointF cP = new PointF ((p.X + previousPoint1.X)/2, (p.Y + previousPoint1.Y)/2); 

     currentPath.AddQuadCurveToPoint (cP, previousPoint1); 
     previousPoint1 = p; 
    } 
    else 
     currentPath.AddLineTo (p); 

    InvokeOnMainThread (() => { 
     this.SetNeedsDisplay(); 
    }); 
} 

TouchesEndedTouchesCancelled將重繪視圖:

public override void TouchesEnded (MonoTouch.Foundation.NSSet touches, UIEvent evt) 
{ 
    InvokeOnMainThread (() => { 
     this.SetNeedsDisplay(); 
    }); 
} 

public override void TouchesCancelled (MonoTouch.Foundation.NSSet touches, UIEvent evt) 
{ 
    InvokeOnMainThread (() => { 
     this.SetNeedsDisplay(); 
    }); 
} 

最後,Draw方法被重寫來迭代的路徑的陣列,繪製每個其中一個使用相應的顏色:

public override void Draw (System.Drawing.RectangleF rect) 
{ 
    foreach (VESLine p in lines) { 
     p.Color.SetStroke(); 
     p.Path.Stroke(); 
    } 
} 
+1

非常感謝您的回答。它絕對幫助我。我還想補充一點,我得到了一些來自畫線的瘋狂的尖峯,我可以通過在'TouchesBegan'內的'UIBezierPath'對象中包含以下屬性來解決這個問題:'UIBezierPath path = new UIBezierPath { LineJoinStyle = CGLineJoin.Round, LineCapStyle = CGLineCap.Round };' – hvaughan3

+0

不是我懷疑你,但根據Bezier路徑文檔,它只是標準CGPath相關功能的包裝,所以它可以做什麼,你可以CGPath已經做不到了? –