Проблема в рисовании линии с использованием основной графики: отображаются пузырьки

Используя основную графику, я пытаюсь нарисовать строку, в которой, когда я пытаюсь добавить тень, создается lin и пузыри внутри строки, см. изображение, я не могу решить проблему. пожалуйста, найдите мой код ниже

-(void)drawRect:(CGRect)rect
{

    [curImage drawAtPoint:CGPointMake(0, 0)];
    CGPoint mid1 = midPoint(previousPoint1, previousPoint2); 
    CGPoint mid2 = midPoint(currentPoint, previousPoint1);

    CGContextRef context = UIGraphicsGetCurrentContext(); 

    [self.layer renderInContext:context];

    CGContextMoveToPoint(context, mid1.x, mid1.y);
    CGContextAddQuadCurveToPoint(context, previousPoint1.x, previousPoint1.y, mid2.x, mid2.y); 
    CGContextSetLineCap(context, kCGLineCapRound);
    CGContextSetLineWidth(context, self.lineWidth);
    CGContextSetStrokeColorWithColor(context, self.lineColor.CGColor);

    CGContextSetShadow(context, CGSizeMake(-16.00, -5.0f), 5.0f);

    CGContextStrokePath(context);

    [super drawRect:rect];

    [curImage release];

}

Ниже приведен метод touchesMoved.

-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{

    UITouch *touch  = [touches anyObject];

    previousPoint2  = previousPoint1;
    previousPoint1  = [touch previousLocationInView:self];
    currentPoint    = [touch locationInView:self];

    // calculate mid point
    CGPoint mid1    = midPoint(previousPoint1, previousPoint2); 
    CGPoint mid2    = midPoint(currentPoint, previousPoint1);

    CGMutablePathRef path = CGPathCreateMutable();
    CGPathMoveToPoint(path, NULL, mid1.x, mid1.y);
    CGPathAddQuadCurveToPoint(path, NULL, previousPoint1.x, previousPoint1.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        -= self.lineWidth * 2;
    drawBox.origin.y        -= self.lineWidth * 2;
    drawBox.size.width      += self.lineWidth * 4;
    drawBox.size.height     += self.lineWidth * 4;

    UIGraphicsBeginImageContext(drawBox.size);
    [self.layer renderInContext:UIGraphicsGetCurrentContext()];
    curImage = UIGraphicsGetImageFromCurrentImageContext();
    [curImage retain];
    UIGraphicsEndImageContext();
   [self setNeedsDisplayInRect:drawBox];

}

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


-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{

    UITouch *touch = [touches anyObject];

    previousPoint1 = [touch previousLocationInView:self];
    previousPoint2 = [touch previousLocationInView:self];
    currentPoint = [touch locationInView:self];

    [self touchesMoved:touches withEvent:event];
}

Здесь проблема возникает, когда я пытаюсь добавить строку

CGContextSetShadow(context, CGSizeMake(-16.00, -5.0f), 5.0f); 

Issue image

Пожалуйста, помогите мне в этом вопросе, спасибо заранее. см. редактирование вопроса с помощью методов.

Ответ 1

Похоже, вы рисуете серию сегментов как квад-кривые. Пузыри были бы там, где предыдущий сегмент и текущий сегмент перекрываются. Поскольку ваша сегментная линия является сплошной красной, вы не заметите перекрытие, но оно появляется в тени как более темные области.

Попробуйте установить цвет вашего штриха и альфа 0,5 (или некоторую такую ​​полупрозрачность). Я думаю (знаю), вы увидите, что перекрывающиеся сегменты также будут показывать аналогичный эффект, чем тень.

Чтобы решить эту проблему, вы захотите провести сегмент как непрерывный путь для каждой строки. Я предполагаю, что вы используете touchesBegan:withEvent:/touchesMoved:withEvent/touchesEnded:withEvent: для получения точек линий?

В этом случае, когда вызывается touchesBegan:withEvent:, запустите свой новый путь. Во время touchesMoved:withEvent визуализируйте новый путь по текущему изображению. Зафиксируйте путь к UIImage в touchesEnded:withEvent:. На этом этапе вы можете отбросить путь до тех пор, пока touchesBegan:withEvent: не будет вызван с последующим штрихом.

Обновление

В ваших фрагментах кода вы оказываете полный просмотр всего три раза за каждый цикл цикла. Это много накладных расходов. Я быстро собрал код, который демонстрирует, о чем я говорю выше. Это не проверенный код, но он должен быть в основном правильным:

Обновление 2

У меня было немного времени, чтобы написать и протестировать код, который будет делать то, что вы ищете, на основе моих последних двух комментариев. Этот код находится от контроллера представления вместо самого представления, но с небольшой модификацией вы можете перемещаться в виде, если хотите. Таким образом, я добавил UIImageView как подпункт общего UIView для хранения и отображения изображения (и содержал ссылку в контроллере представления) и сделал контроллер представления первым ответчиком, чтобы получить прикосновение Мероприятия. Много жестко закодированных значений, которые вы можете очистить при интеграции в свой собственный проект:

static
UIImage *CreateImage( CGRect rect, NSArray *paths )
{
    UIGraphicsBeginImageContextWithOptions(rect.size, NO, 1.0);
    CGContextRef context = UIGraphicsGetCurrentContext();

    CGFloat colorComponents[4] = {0.0,0.0,0.0,0.0};
    CGContextSetFillColor(context, colorComponents);
    CGContextFillRect(context, rect);

    for ( id obj in paths ) {
        CGPathRef path = (CGPathRef)obj;
        CGContextAddPath(context, path);
    }    
    CGContextSetStrokeColorWithColor(context, [[UIColor redColor] CGColor]);
    CGContextSetLineCap(context, kCGLineCapRound);
    CGContextSetLineWidth(context, 5.0);
    CGContextSetShadow(context, (CGSize){-8.0,40}, 5.0);
    CGContextBeginTransparencyLayer(context, NULL);

    CGContextDrawPath(context, kCGPathStroke);

    CGContextEndTransparencyLayer(context);

    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return image;
}

static
CGPoint MidPoint( CGPoint pt1, CGPoint pt2 )
{
    return (CGPoint){(pt1.x+pt2.x)/2.0,(pt1.y+pt2.y)/2.0};
}

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    [super touchesBegan:touches withEvent:event];
    CGPoint location = [[touches anyObject] locationInView:self.view];
    myPath = CGPathCreateMutable();
    CGPathMoveToPoint(myPath, NULL, location.x, location.y);

    [self.paths addObject:(id)myPath];
}

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
    [super touchesMoved:touches withEvent:event];
    UITouch *touch = [touches anyObject];
    CGPoint previousLocation = [touch previousLocationInView:self.view];
    CGPoint location = [touch locationInView:self.view];
    CGPoint midPoint = MidPoint(previousLocation, location);
    CGPathAddQuadCurveToPoint(myPath, NULL, midPoint.x, midPoint.y, location.x, location.y);

    self.imageView.image = CreateImage(self.view.bounds, self.paths);
}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
    [super touchesEnded:touches withEvent:event];
    UITouch *touch = [touches anyObject];
    CGPoint previousLocation = [touch previousLocationInView:self.view];
    CGPoint location = [touch locationInView:self.view];
    CGPoint midPoint = MidPoint(previousLocation, location);
    CGPathAddQuadCurveToPoint(myPath, NULL, midPoint.x, midPoint.y, location.x, location.y);

    self.imageView.image = CreateImage(self.view.bounds, self.paths);

    CGPathRelease(myPath);
    myPath = nil;
}

Ответ 2

проблема в том, что у вас есть несколько строк, которые лежат друг над другом. Таким образом тени обоих перекрываются, и вы получаете более темный цвет.

Для чего-то, что легко, как ваши линейные чертежи, вы можете просто скопировать весь код чертежа и перерисовать другим цветом и смещением пиксела представления (вместо тени). Например. вы сохраняете кривые в массиве и рисуете их по отдельности позже.

EDIT:
ok @gschandler также описывает проблему.

Но вам также может понравиться документация Transparency Layer. Группируйте элементы вместе и применяйте тень для группы.

Ответ 3

Другим способом для этого является создание массива точек при перемещении событий касания, а затем их рисование.

Создайте массив точек:

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
[pointArray release]; pointArray = nil;
pointArray=[[NSMutableArray alloc] init];
UITouch *touch = [touches anyObject];
[bufferArray removeAllObjects];

previousPoint1 = [touch previousLocationInView:self];
previousPoint2 = [touch previousLocationInView:self];
currentPoint = [touch locationInView:self];

}


-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
previousPoint2 = previousPoint1;
previousPoint1 = [touch previousLocationInView:self];
currentPoint = [touch locationInView:self];
[pointArray addObject: [NSValue valueWithCGPoint:previousPoint2]];
[pointArray addObject:[NSValue valueWithCGPoint:previousPoint1]];   
[pointArray addObject:[NSValue valueWithCGPoint:currentPoint]];
[self setNeedsDisplay];
}

-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{   

}


-(void)drawRect:(CGRect)rect
{
CGContextRef context = UIGraphicsGetCurrentContext(); 
CGContextSetLineCap(context, kCGLineCapRound);
CGContextSetLineWidth(context, self.lineWidth);
CGContextSetStrokeColorWithColor(context, self.lineColor.CGColor);

CGContextSetShadow(context, CGSizeMake(-16.00, -5.0f), 5.0f);

for(int i = 1 ; i < [pointArray count]-1;i++)
{
CGPoint mid1 = midPoint([pointArray objectAtIndex:i+1], [pointArray objectAtIndex:i]); 
CGPoint mid2 = midPoint([pointArray objectAtIndex:i+2], [pointArray objectAtIndex:i+1]);


CGContextMoveToPoint(context, mid1.x, mid1.y);
CGContextAddQuadCurveToPoint(context, previousPoint1.x, previousPoint1.y, mid2.x, mid2.y); 
i+=2;
}
CGContextStrokePath(context);

}

Вы можете управлять несколькими строками с помощью многомерного массива:)