3

我想用我的手指画一条直线,它会根据我与原点的距离自动调整大小。

因此,如果我在中间触摸屏幕并将手指滑出,当我的手指在屏幕上移动时,一条线似乎会“伸展”并围绕原点旋转。当我抬起我的手指。目标点应最终确定并创建一条线。我可以在屏幕上拖动手指并在屏幕上“绘制”,但这不是我想要做的。

我认为 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];
}
4

2 回答 2

4

这是一个概念。从您开始拖动手指的位置到松开的位置绘制一条线,并在您拖动手指时对其进行动画处理。它通过制作, 在您移动手指时CAShapeLayer重置来做到这一点。path

这应该证明基本思想:

- (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,但您想跟踪以前的路径,则必须为这些旧路径维护一个数组,并构建一个包含所有旧路径的路径,可能类似于:

@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
于 2013-01-07T20:02:51.750 回答
2

UIBezierPath 正在根据您的指示构建路径。想象一支笔。当您说“moveToPoint:”时,它会将笔移动到该点。当您说“lineToPoint:”时,它会放下笔并将其从当前位置移动到新点。等等。

为了获得您想要的效果,您需要在触摸移动时创建一条新路径,从原始点到当前触摸位置绘制一条线。

于 2013-01-07T19:35:17.860 回答