2014-01-29 65 views
2

我在圖紙上的應用程序施工圖,我想要做的撤銷/重做,爲此我對觸摸節省CGPath端到NSMutableArray的,但我不理解我應該怎麼上呈現CGPaths點擊撤銷按鈕,撤銷/重做用於iOS的

EDIT1:

由於我使用BezierPaths,於是,我第一次決定一起去的只是撫摸着這條路,沒有CGPath一個簡單的方法,

EDIT2:由於我的撤銷是發生在細分(我,部分而不是整個路徑被刪除),我決定創建一個數組的數組,所以我做了相應的改變,現在我將繪製CGlay呃,帶着CGPath

所以這裏「parentUndoArray」是數組的數組。

所以我做了這樣

我有一個名爲DrawingPath將做繪圖

//DrawingPath.h 

@interface DrawingPath : NSObject 

@property (strong, nonatomic) NSString *pathWidth; 
@property (strong,nonatomic) UIColor  *pathColor; 
@property (strong,nonatomic) UIBezierPath *path; 

- (void)draw; 

@end 

//DrawingPath.m 

#import "DrawingPath.h" 

@implementation DrawingPath 


@synthesize pathWidth = _pathWidth; 
@synthesize pathColor = _pathColor; 
@synthesize path = _path; 


- (id)init { 

    if (!(self = [super init])) 
     return nil; 



    _path = [[UIBezierPath alloc] init]; 
    _path.lineCapStyle=kCGLineCapRound; 
    _path.lineJoinStyle=kCGLineJoinRound; 

    [_path setLineWidth:2.0f]; 

    return self; 
} 

- (void)draw 
{ 

    [self.pathColor setStroke]; 
    [self.path stroke]; 

} 

所以現在我DrawingView類,我做這種方式

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event 
{ 
    ctr = 0; 
    bufIdx = 0; 
    UITouch *touch = [touches anyObject]; 
    pts[0] = [touch locationInView:self]; 
    isFirstTouchPoint = YES; 

    [m_undoArray removeAllObjects];//On every touches began clear undoArray 

} 

-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event 
{ 
      UITouch *touch = [touches anyObject]; 

      CGPoint p = [touch locationInView:self]; 
      ctr++; 
      pts[ctr] = p; 


      if (ctr == 4) 
      { 
       pts[3] = midPoint(pts[2], pts[4]); 


       for (int i = 0; i < 4; i++) 
       { 
        pointsBuffer[bufIdx + i] = pts[i]; 
       } 

       bufIdx += 4; 

       dispatch_async(drawingQueue, ^{ 


        self.currentPath = [[DrawingPath alloc] init]; 
        [self.currentPath setPathColor:self.lineColor]; 

        if (bufIdx == 0) return; 

        LineSegment ls[4]; 
        for (int i = 0; i < bufIdx; i += 4) 
        { 
         if (isFirstTouchPoint) // ................. (3) 
         { 

          ls[0] = (LineSegment){pointsBuffer[0], pointsBuffer[0]}; 
          [self.currentPath.path moveToPoint:ls[0].firstPoint]; 


          // [offsetPath addLineToPoint:ls[0].firstPoint]; 
          isFirstTouchPoint = NO; 

         } 
         else 
         { 
          ls[0] = lastSegmentOfPrev; 

         } 


         float frac1 = self.lineWidth/clamp(len_sq(pointsBuffer[i], pointsBuffer[i+1]), LOWER, UPPER); // ................. (4) 
         float frac2 = self.lineWidth/clamp(len_sq(pointsBuffer[i+1], pointsBuffer[i+2]), LOWER, UPPER); 
         float frac3 = self.lineWidth/clamp(len_sq(pointsBuffer[i+2], pointsBuffer[i+3]), LOWER, UPPER); 


         ls[1] = [self lineSegmentPerpendicularTo:(LineSegment){pointsBuffer[i], pointsBuffer[i+1]} ofRelativeLength:frac1]; // ................. (5) 
         ls[2] = [self lineSegmentPerpendicularTo:(LineSegment){pointsBuffer[i+1], pointsBuffer[i+2]} ofRelativeLength:frac2]; 
         ls[3] = [self lineSegmentPerpendicularTo:(LineSegment){pointsBuffer[i+2], pointsBuffer[i+3]} ofRelativeLength:frac3]; 


         [self.currentPath.path moveToPoint:ls[0].firstPoint]; // ................. (6) 
         [self.currentPath.path addCurveToPoint:ls[3].firstPoint controlPoint1:ls[1].firstPoint controlPoint2:ls[2].firstPoint]; 
         [self.currentPath.path addLineToPoint:ls[3].secondPoint]; 
         [self.currentPath.path addCurveToPoint:ls[0].secondPoint controlPoint1:ls[2].secondPoint controlPoint2:ls[1].secondPoint]; 
         [self.currentPath.path closePath]; 

         lastSegmentOfPrev = ls[3]; // ................. (7) 
        }  


        [m_undoArray addObject:self.currentPath]; 

        EDIT:2 
        CGPathRef cgPath = self.currentPath.path.CGPath; 
        mutablePath = CGPathCreateMutableCopy(cgPath); 


        dispatch_async(dispatch_get_main_queue(), ^{ 
        bufIdx = 0; 
        [self setNeedsDisplay]; 

         }); 
        }); 


       pts[0] = pts[3]; 
       pts[1] = pts[4]; 
       ctr = 1; 
      } 
     } 
    } 
} 

-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event 
{  
    [parentUndoArray addObject:m_undoArray]; 

} 

我的drawRect方法是低於

編輯:現在我的DrawRect有兩種情況

- (void)drawRect:(CGRect)rect 
{  
    switch (m_drawStep) 
    { 
     case DRAW: 
     { 

      CGContextRef context = UIGraphicsGetCurrentContext();//Get a reference to current context(The context to draw) 



      CGContextRef layerContext = CGLayerGetContext(self.currentDrawingLayer); 
      CGContextBeginPath(layerContext); 
      CGContextAddPath(layerContext, mutablePath); 
      CGContextSetStrokeColorWithColor(layerContext, self.lineColor.CGColor); 
      CGContextSetFillColorWithColor(layerContext, self.lineColor.CGColor); 
      CGContextSetBlendMode(layerContext,kCGBlendModeNormal); 
      CGContextDrawPath(layerContext, kCGPathFillStroke); 
      // CGPathRelease(mutablePath); 



      CGContextDrawLayerInRect(context,rectSize, self.newDrawingLayer); 
      CGContextDrawLayerInRect(context, self.bounds, self.permanentDrawingLayer); 
      CGContextDrawLayerInRect(context, self.bounds, self.currentDrawingLayer); 

      } 
      break; 




     case UNDO: 
     {   
      for(int i = 0; i<[m_parentUndoArray count];i++) 
      { 
       NSMutableArray *undoArray = [m_parentUndoArray objectAtIndex:i]; 

       for(int i =0; i<[undoArray count];i++) 
       { 
        DrawingPath *drawPath = [undoArray objectAtIndex:i]; 
        [drawPath draw]; 
       } 
      } 


     } 
      break; 


     [super drawRect:rect]; 
} 

編輯2:現在,我現在面臨的問題是,即使我繪製小路徑或大路徑,陣列數組中的數據是相同的。但是INFACT,小路徑應該含有較少drawingPath對象和大的路徑應包含在undoArray更drawingPath對象,它在最後被添加到陣列的陣列稱爲「ParentUndoArray

下面是屏幕截圖,

1。一氣描線的第一截屏無需提起手指

enter image description here

2,做撤消操作一次,只有線的段被去除之後

enter image description here

回答

2

我已經找到了一個解決方案,我們需要創建的DrawingPaths數組的數組:

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event 
{ 
    // Do the above code, then 
    [m_undoArray addObject:self.currentPath]; 
} 

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event 
{ 
    [m_parentUndoArray addObject:[NSArray arrayWithArray:m_undoArray]]; 
} 

,然後中風DrawRect的路徑。

+0

如何在這個鏈接中實現撤消功能回答..http:// stackoverflow .com/questions/23997525/how-to-draw-calayer-with-line-path-like-simulate-eraser-effect請幫助我.. –

1

如果您的drawRect方法可以得出任何CGPaths在數組中,所有你需要做的是通過調用setNeedsDisplay觸發圖紙再次撤消方法您已經刪除最後添加CGPath

+0

Hello Niraj,如果你仔細看看我的代碼,你會注意到,我在touchesMoved中完成了可變寬度,在這裏我只是從UIBezeirPath中取出CgPath並繪製它。 – Ranjit

+0

可能,我沒有很好地理解這個問題,但似乎你需要在任何給定的時間點重繪NSMutableArray中的路徑。如果是這樣的話,你應該將繪圖代碼從touchesMoved移動到一個單獨的方法 – Niraj

1

我想以後你製作的路徑對象比你想要的要多。我建議轉到您的Alloc的bezierPath在觸摸移動並更換

self.currentPath = [[DrawingPath alloc] init]; 

隨着

if(!self.currentPath){ 
        self.currentPath = [[DrawingPath alloc] init]; 
} 
+0

我試過了,會發生什麼情況是,如果我畫兩條線,然後如果我按撤消,那麼第二行不會去,我有兩次點擊撤消3-4次,然後第二行消失,類似地,對於第一行 – Ranjit

+0

撤消代碼在哪裏交配?不要擔心,我們可以做到這一點:) – Jef

+0

我會發布它,給我兩分鐘 – Ranjit

0

那麼你應該這樣做,因爲它很容易

- (id)initWithFrame:(CGRect)frame 
{ 
    self = [super initWithFrame:frame]; 
    if (self) { 
    // Initialization code 

    self.backgroundColor = [UIColor clearColor]; 
    myPath = [[UIBezierPath alloc] init]; 
    myPath.lineCapStyle = kCGLineCapRound; 
    myPath.miterLimit = 0; 
    bSize=5; 
    myPath.lineWidth = bSize; 
    brushPattern = [UIColor whiteColor]; 

    // Arrays for saving undo-redo steps in arrays 
    pathArray = [[NSMutableArray alloc] init]; 
    bufferArray = [[NSMutableArray alloc] init]; 


    } 
return self; 
} 

// Only override drawRect: if you perform custom drawing. 

// An empty implementation adversely affects performance during animation. 

- (void)drawRect:(CGRect)rect 
{ 
    [brushPattern setStroke]; 
    for (id path in pathArray){ 
     if ([path isKindOfClass:[UIBezierPath class]]) { 
      UIBezierPath *_path=(UIBezierPath *)path; 
      [_path strokeWithBlendMode:kCGBlendModeNormal alpha:1.0]; 
     } 
    } 
} 

#pragma mark - Touch Methods 
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event 
{ 

     UITouch *mytouch = [[touches allObjects] objectAtIndex:0]; 
     myPath = [[UIBezierPath alloc] init]; 
     myPath.lineWidth = bSize; 
     [myPath moveToPoint:[mytouch locationInView:self]]; 
     [pathArray addObject:myPath]; 

} 

-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event 
{ 
    [myPath addLineToPoint:[[touches anyObject] locationInView:self]]; 
    [self setNeedsDisplay]; 
} 


#pragma mark - Undo Method 
-(void)undoButtonClicked 
{ 
    if([pathArray count]>0) 
    { 
     if ([[pathArray lastObject] isKindOfClass:[SPUserResizableView class]]) 
     { 
      [[pathArray lastObject] removeFromSuperview]; 
     } 
    UIBezierPath *_path = [pathArray lastObject]; 
    [bufferArray addObject:_path]; 
    [pathArray removeLastObject]; 
    [self setNeedsDisplay]; 
    } 

} 
-(void)setBrushSize: (CGFloat)brushSize 
{ 
    bSize=brushSize; 
} 

-(void)redoButtonClicked 
{ 
    if([bufferArray count]>0){ 
    UIBezierPath *_path = [bufferArray lastObject]; 
    [pathArray addObject:_path]; 
    [bufferArray removeLastObject]; 
    [self setNeedsDisplay]; 
    } 
} 
-(void)undoAllButtonClicked 
{ 
    [pathArray removeAllObjects]; 
    [self setNeedsDisplay]; 
} 

希望這將有助於。