Я работаю над графическим приложением, я хочу сделать Undo/Redo, для этого я сохраняю CGPath при прикосновениях, заканчивающихся до NSMutableArray, но я не понимаю, как я должен отображать CGPaths на нажмите на кнопку ОтменитьUndo/Redo для рисования в iOS
EDIT1:
Как я использую BezierPaths, Итак, я первый решил пойти с простым подходом просто поглаживая по этому пути, без CGPath,
edit2: Как моя Undo является происходит в сегментах (i, e по частям и не весь путь удаляется), я решил создать массив массивов, поэтому я внес соответствующие изменения, и теперь я буду рисовать CGlay er, с принятием 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 ниже
EDIT: теперь у меня 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];
}
EDIT2: Теперь проблема, что я столкнулся в настоящее время является то, что, даже если я рисую маленькие дорожки или большие пути, данные в массиве массива же. Но Infact, малый путь должен содержать меньший объект drawingPath и большой путь должен содержать больше drawingPath объект в undoArray, который наконец-то добавляется в массив массив под названием «ParentUndoArray
Вот скриншоты,
1. первый снимок экрана нарисованной линии на участке, не снимая палец
2, После выполнения операции отмены один раз, только сегмент этой линии удаляется
Как реализовать функцию отмены в этих ссылках ответ ..http: // stackoverflow .com/questions/23997525/how-to-draw-calayer-with-line-path-like-simulate-eraser-effect, пожалуйста, помогите мне .. –