伸展的UIBezierPath线?
我想用我的手指画出一条直线,根据我离原点的距离来自动resize。
所以如果我在中间触摸屏幕并且滑动我的手指,当我的手指在屏幕上移动时,一条线似乎“伸展”并围绕orgin点旋转。 当我抬起我的手指。 目的地点应最终确定并创build一条线。 我可以将手指拖过屏幕,然后在屏幕上“绘制”,但这不是我想要做的。
我认为UIBeizerPath moveToPoint会帮助,但它只是弄乱了事情。
我究竟做错了什么?
- (id)initWithFrame:(CGRect)frame { //default line properties myPath=[[UIBezierPath alloc]init]; myPath.lineCapStyle=kCGLineCapRound; myPath.miterLimit=0; myPath.lineWidth=lineWidth; brushPattern=[UIColor blackColor]; } -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { CGPoint curPoint = [[touches anyObject] locationInView:self]; lastPoint = curPoint; [myPath moveToPoint:lastPoint]; [pathArray addObject:myPath]; [self setNeedsDisplay]; } -(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{ CGPoint curPoint = [[touches anyObject] locationInView:self]; myPath.lineWidth=lineWidth; brushPattern=[UIColor redColor]; //red to show it hasn't been added yet. [myPath moveToPoint:tempPoint]; [self setNeedsDisplay]; } -(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { CGPoint curPoint = [[touches anyObject] locationInView:self]; myPath.lineWidth=lineWidth; brushPattern=[UIColor blackColor]; //finalize the line with black color [myPath addLineToPoint:curPoint]; [self setNeedsDisplay]; }
这是一个概念。 从您开始拖动手指的位置开始画一条线,直到您放开的位置,然后在您拖动手指的同时对其进行animation处理。 它通过制作一个CAShapeLayer
,在你移动手指的时候重置path
。
这应该certificate基本的想法:
- (void)viewDidLoad { [super viewDidLoad]; UIPanGestureRecognizer *gesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePanGesture:)]; [self.view addGestureRecognizer:gesture]; } - (CAShapeLayer *)createShapeLayer:(UIView *)view { CAShapeLayer *shapeLayer = [[CAShapeLayer alloc] init]; shapeLayer.fillColor = [UIColor clearColor].CGColor; shapeLayer.strokeColor = [UIColor redColor].CGColor; shapeLayer.lineWidth = 3.0; [view.layer addSublayer:shapeLayer]; return shapeLayer; } - (void)handlePanGesture:(UIPanGestureRecognizer *)gesture { static CAShapeLayer *shapeLayer; static CGPoint origin; if (gesture.state == UIGestureRecognizerStateBegan) { shapeLayer = [self createShapeLayer:gesture.view]; origin = [gesture locationInView:gesture.view]; } else if (gesture.state == UIGestureRecognizerStateChanged) { UIBezierPath *path = [UIBezierPath bezierPath]; [path moveToPoint:origin]; CGPoint location = [gesture locationInView:gesture.view]; [path addLineToPoint:location]; shapeLayer.path = path.CGPath; } else if (gesture.state == UIGestureRecognizerStateEnded || gesture.state == UIGestureRecognizerStateFailed || gesture.state == UIGestureRecognizerStateCancelled) { shapeLayer = nil; } }
或者,在Swift 3:
override func viewDidLoad() { super.viewDidLoad() let pan = UIPanGestureRecognizer(target: self, action: #selector(handlePan(_:))) view.addGestureRecognizer(pan) } private func createShapeLayer(for view: UIView) -> CAShapeLayer { let shapeLayer = CAShapeLayer() shapeLayer.fillColor = UIColor.clear.cgColor shapeLayer.strokeColor = UIColor.red.cgColor shapeLayer.lineWidth = 3.0 view.layer.addSublayer(shapeLayer) return shapeLayer } private var shapeLayer: CAShapeLayer! private var origin: CGPoint! func handlePan(_ gesture: UIPanGestureRecognizer) { if gesture.state == .began { shapeLayer = createShapeLayer(for: gesture.view!) origin = gesture.location(in: gesture.view) } else if gesture.state == .changed { let path = UIBezierPath() path.move(to: origin) path.addLine(to: gesture.location(in: gesture.view)) shapeLayer.path = path.cgPath } else if gesture.state == .ended || gesture.state == .failed || gesture.state == .cancelled { shapeLayer = nil } }
如果你不使用CAShapeLayer
,但是你想跟踪以前的path,那么你必须为这些旧path维护一个数组,并且构build一个由所有旧path组成的path,可能类似于:
@interface CustomView () @property (nonatomic) CGPoint originPoint; @property (nonatomic) CGPoint currentPoint; @property (nonatomic) NSMutableArray *previousPaths; @end @implementation CustomView - (id)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { [self configure]; } return self; } - (id)init { return [self initWithFrame:CGRectZero]; } - (id)initWithCoder:(NSCoder *)aDecoder { self = [super initWithCoder:aDecoder]; if (self) { [self configure]; } return self; } - (void)configure { _previousPaths = [[NSMutableArray alloc] init]; } - (void)drawRect:(CGRect)rect { [[UIColor redColor] setStroke]; UIBezierPath *drawPath = [UIBezierPath bezierPath]; drawPath.lineCapStyle = kCGLineCapRound; drawPath.miterLimit = 0; drawPath.lineWidth = 3.0; for (UIBezierPath *path in self.previousPaths) [drawPath appendPath:path]; UIBezierPath *path = [self pathForCurrentLine]; if (path) [drawPath appendPath:path]; [drawPath stroke]; } - (UIBezierPath *)pathForCurrentLine { if (CGPointEqualToPoint(self.originPoint, CGPointZero) && CGPointEqualToPoint(self.currentPoint, CGPointZero)) return nil; UIBezierPath *path = [UIBezierPath bezierPath]; [path moveToPoint:self.originPoint]; [path addLineToPoint:self.currentPoint]; return path; } - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { self.originPoint = [[touches anyObject] locationInView:self]; } - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { UITouch *touch = [touches anyObject]; if ([event respondsToSelector:@selector(predictedTouchesForTouch:)]) { touch = [[event predictedTouchesForTouch:touch] lastObject] ?: touch; } self.currentPoint = [touch locationInView:self]; [self setNeedsDisplay]; } - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { self.currentPoint = [[touches anyObject] locationInView:self]; [self.previousPaths addObject:[self pathForCurrentLine]]; self.originPoint = self.currentPoint = CGPointZero; [self setNeedsDisplay]; } @end
UIBezierPath正在根据您的指示构build一条path。 想象一支笔。 当你说,“moveToPoint:”它移动笔到那一点。 当你说“lineToPoint:”它放下笔,并从当前位置移动到新的点。 等等。
为了达到你想要的效果,每当触摸移动时,你都需要创build一个新的path,从原点到当前的触摸位置画一条线。