我正在开发一个绘图应用程序,我想做撤消/重做,为此我将触摸结束时的 CGPath 保存到 NSMutableArray,但我不明白如何在单击撤消按钮时呈现 CGPaths
编辑1:
由于我使用的是 BezierPaths,所以,我首先决定采用一种简单的方法,即在不使用 CGPath 的情况下抚摸这条路径,
EDIT2:由于我的撤消是在分段中进行的(即,部分而不是整个路径被删除),我决定创建一个数组数组,所以我进行了相应的更改,现在我将在 CGlayer 中绘制,用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)touchesBeganNSSet *)touches withEventUIEvent *)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)touchesMovedNSSet *)touches withEventUIEvent *)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 lineSegmentPerpendicularToLineSegment){pointsBuffer[i], pointsBuffer[i+1]} ofRelativeLength:frac1]; // ................. (5)
ls[2] = [self lineSegmentPerpendicularToLineSegment){pointsBuffer[i+1], pointsBuffer[i+2]} ofRelativeLength:frac2];
ls[3] = [self lineSegmentPerpendicularToLineSegment){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)touchesEndedNSSet *)touches withEventUIEvent *)event
{
[parentUndoArray addObject:m_undoArray];
}
下面是我的drawRect方法
编辑:现在我的 DrawRect 有两种情况
- (void)drawRectCGRect)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:现在我面临的问题是,即使我绘制小路径或大路径,数组数组中的数据都是相同的。但实际上,小路径应该包含较少的drawingPath对象,大路径应该包含更多的undoArray中的drawingPath对象,最后添加到名为“ParentUndoArray”的数组数组中
这是屏幕截图,
1.第一屏不抬手指,一气呵成的画线截图
2、执行一次undo操作后,只删除该行的一部分
Best Answer-推荐答案 strong>
我已经找到了解决方案,我们需要创建一个 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 中描边路径。
关于ios - 在 iOS 中撤消/重做绘图,我们在Stack Overflow上找到一个类似的问题:
https://stackoverflow.com/questions/21438586/
|