在UIView中的贝塞尔曲线路径内像素描颜色一样绘制/绘画 [英] Draw/Paint like sketch color inside a bezier path in UIView

查看:82
本文介绍了在UIView中的贝塞尔曲线路径内像素描颜色一样绘制/绘画的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在UIView上的UIBezier路径的帮助下绘制形状层:

  CAShapeLayer * pathLayer = [CAShapeLayer层]; 
pathLayer.frame = CGRectMake(-view.frame.origin.x,-view.frame.origin.y,view.frame.size.width,view.frame.size.height);
pathLayer.path = path.CGPath;
pathLayer.strokeColor = [[UIColor blackColor] CGColor];
pathLayer.fillColor = [[UIColor clearColor] CGColor];
//pathLayer.fillColor = nil;
pathLayer.lineWidth = 6.0;
pathLayer.lineJoin = kCALineJoinBevel;
[view.layer addSublayer:pathLayer];

在触摸点上,我想在该UIView上进行绘制,为此:

 -(void)touches开始:(NSSet *)touches withEvent:(UIEvent *)event 
{
UITouch * touch = [触摸anyObject];
CGPoint touchBeganPoint;
touchBeganPoint = [触摸locationInView:self];
actionString = @ drawPencil;
previousPoint1 = [touch locationInView:self];
previousPoint2 = [touch locationInView:self];
currentPoint = [touch locationInView:self];
[self touchesMoved:touches withEvent:event];
}

-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch * touch = [touches anyObject];
previousPoint2 = previousPoint1;
previousPoint1 = currentPoint;
currentPoint = [touch locationInView:self];
[self computeMinImageArea:previousPoint1:previousPoint2:currentPoint];
}

CGPoint midPoint(CGPoint p1,CGPoint p2)//辅助函数
{
return CGPointMake((p1.x + p2.x)* 0.5, (p1.y + p2.y)* 0.5);
}

-(void)calculateMinImageArea:(CGPoint)pp1:(CGPoint)pp2:(CGPoint)cp
{
//计算中点
CGPoint mid1 = midPoint(pp1,pp2);
CGPoint mid2 = midPoint(cp,pp1);

CGMutablePathRef路径= CGPathCreateMutable();
CGPathMoveToPoint(path,NULL,mid1.x,mid1.y);
CGPathAddQuadCurveToPoint(path,NULL,pp1.x,pp1.y,mid2.x,mid2.y);
CGRect范围= CGPathGetBoundingBox(path);
CGPathRelease(path);

CGRect drawBox =范围;

//填充我们的值,使边界框尊重我们的线宽
drawBox.origin.x-= 20 * 1.5;
drawBox.origin.y-= 20 * 1.5;
drawBox.size.width + = 20 * 2.5;
drawBox.size.height + = 20 * 2.5;

UIGraphicsBeginImageContextWithOptions(drawBox.size,NO,0);
[self.layer renderInContext:UIGraphicsGetCurrentContext()];
curImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

//在此处生成if条件,然后检查并绘制路径
[self setNeedsDisplayInRect:drawBox];
[[NSRunLoop currentRunLoop] runMode:NSRunLoopCommonModes beforeDate:[NSDate date]];
}

-(void)drawRect:(CGRect)rect
{
CGPoint mid1 = midPoint(previousPoint1,previousPoint2);
CGPoint mid2 = midPoint(currentPoint,previousPoint1);
[curImage drawAtPoint:CGPointMake(0,0)];
CGContextRef context = UIGraphicsGetCurrentContext();
CALayer * layer = [self.layer.sublayers objectAtIndex:0];
[self.layer renderInContext:context];
CGContextMoveToPoint(context,mid1.x,mid1.y);
CGContextAddQuadCurveToPoint(context,previousPoint1.x,previousPoint1.y,mid2.x,mid2.y);
CGContextSetLineCap(context,kCGLineCapRound);
CGContextSetBlendMode(context,kCGBlendModeNormal);
CGContextSetLineJoin(context,kCGLineJoinRound);
CGContextSetLineWidth(context,20);
CGContextSetStrokeColorWithColor(context,[UIColor redColor] .CGColor);
CGContextSetShouldAntialias(context,YES);
CGContextSetAllowsAntialiasing(context,YES);
CGContextSetFlatness(context,1.f);
CGContextSetAlpha(context,1.0);
CGContextStrokePath(context);
[super drawRect:rect];
}

现在,当我在self.layer上绘画时,它仍然会影响添加sublayer(shape layer)。我只想在此路径内绘制,不能与[path containspoint ..]一起使用,就像在draw rect中一样,我正在绘制的图像具有一定的宽度,并且它会越过路径或有时会干扰其笔划。 p>

实现此目的的一种方法是将UIView与其子层(CAShapelayer)剪辑在一起,然后在uiview上再次绘制(这将清除形状层区域以外的背景)。



任何有关如何顺利实现此目标的建议或见解都可能会有很大帮助。
谢谢!

解决方案

拍摄另一幅图像,该图像是具有所需路径的视图快照,并填充有选定的颜色。
比触摸移动的方法叫做drawrect,使用相同的代码,但[UIColor colorWithPatternImage:img]作为上下文的颜色略有不同。
在接触点上的UIView中进行绘制会在边界上产生模糊的绘制效果


I am drawing a shape layer with help of a UIBezier Path on a UIView :

    CAShapeLayer *pathLayer = [CAShapeLayer layer];
    pathLayer.frame=CGRectMake(-view.frame.origin.x, -view.frame.origin.y, view.frame.size.width, view.frame.size.height);
    pathLayer.path = path.CGPath;
    pathLayer.strokeColor = [[UIColor blackColor] CGColor];
    pathLayer.fillColor = [[UIColor clearColor] CGColor];
    //pathLayer.fillColor = nil;
    pathLayer.lineWidth = 6.0;
    pathLayer.lineJoin = kCALineJoinBevel;
    [view.layer addSublayer:pathLayer];

On touch points I want to paint on that UIView, for that I am doing :

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
      UITouch *touch=[touches anyObject];
      CGPoint touchBeganPoint;
      touchBeganPoint=[touch locationInView:self];
      actionString=@"drawPencil";
      previousPoint1 = [touch locationInView:self];
      previousPoint2 = [touch locationInView:self];
      currentPoint = [touch locationInView:self];
      [self touchesMoved:touches withEvent:event];
}

-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
      UITouch *touch = [touches anyObject];
      previousPoint2  = previousPoint1;
      previousPoint1  = currentPoint;
      currentPoint    = [touch locationInView:self];
      [self calculateMinImageArea:previousPoint1 :previousPoint2 :currentPoint];
}

CGPoint midPoint(CGPoint p1, CGPoint p2) //helper function
{
    return CGPointMake((p1.x + p2.x) * 0.5, (p1.y + p2.y) * 0.5);
}

- (void)calculateMinImageArea:(CGPoint)pp1 :(CGPoint)pp2 :(CGPoint)cp
{
      // calculate mid point
      CGPoint mid1    = midPoint(pp1, pp2);
      CGPoint mid2    = midPoint(cp, pp1);

      CGMutablePathRef path = CGPathCreateMutable();
      CGPathMoveToPoint(path, NULL, mid1.x, mid1.y);
      CGPathAddQuadCurveToPoint(path, NULL, pp1.x, pp1.y, mid2.x, mid2.y);
      CGRect bounds = CGPathGetBoundingBox(path);
      CGPathRelease(path);

      CGRect drawBox = bounds;

      //Pad our values so the bounding box respects our line width
      drawBox.origin.x        -= 20 * 1.5;
      drawBox.origin.y        -= 20 * 1.5;
      drawBox.size.width      += 20 * 2.5;
      drawBox.size.height     += 20 * 2.5;

      UIGraphicsBeginImageContextWithOptions(drawBox.size, NO, 0);
      [self.layer renderInContext:UIGraphicsGetCurrentContext()];
      curImage = UIGraphicsGetImageFromCurrentImageContext();
      UIGraphicsEndImageContext();

      // generate the if conditionover here and than check and draw over paths
      [self setNeedsDisplayInRect:drawBox];
      [[NSRunLoop currentRunLoop] runMode:NSRunLoopCommonModes beforeDate: [NSDate date]];
}

-(void)drawRect:(CGRect)rect
{
      CGPoint mid1 = midPoint(previousPoint1, previousPoint2);
      CGPoint mid2 = midPoint(currentPoint, previousPoint1);
      [curImage drawAtPoint:CGPointMake(0, 0)];
      CGContextRef context = UIGraphicsGetCurrentContext();
      CALayer *layer=[self.layer.sublayers objectAtIndex:0];
      [self.layer renderInContext:context];
      CGContextMoveToPoint(context, mid1.x, mid1.y);
      CGContextAddQuadCurveToPoint(context, previousPoint1.x, previousPoint1.y, mid2.x, mid2.y);
      CGContextSetLineCap(context, kCGLineCapRound);
      CGContextSetBlendMode(context, kCGBlendModeNormal);
      CGContextSetLineJoin(context, kCGLineJoinRound);
      CGContextSetLineWidth(context, 20);
      CGContextSetStrokeColorWithColor(context,[UIColor redColor].CGColor);
      CGContextSetShouldAntialias(context, YES);
      CGContextSetAllowsAntialiasing(context, YES);
      CGContextSetFlatness(context, 1.f);
      CGContextSetAlpha(context,1.0);
      CGContextStrokePath(context);
      [super drawRect:rect];
}

Now while I am drawing on self.layer ,it is still effecting the added sublayer(shape layer).I want to draw only inside this path , cant go with [path containspoint..] , as in draw rect ,the image i am drawing has some width and it crosses path or disturbs its stroke sometimes.

One way of achieving this is to clip the UIView with its sublayer(CAShapelayer) and thus drawing it again on uiview(this will clear the background apart from the shape layer area).But cant find how to clip it with CAShapeLayer.

Any suggestions or insight on how to achieve this smoothly could be of great help. Thank You !

解决方案

Took another image which is snapshot of view with desired path ,filled with selected color. Than on touches moved called drawrect with same code with a little exception of [UIColor colorWithPatternImage:img] as the color to context. Drawing in UIView on touch points gives blurr drawing effect on boundaries

这篇关于在UIView中的贝塞尔曲线路径内像素描颜色一样绘制/绘画的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆