Проблема в рисовании линии с использованием основной графики: отображаются пузырьки
Используя основную графику, я пытаюсь нарисовать строку, в которой, когда я пытаюсь добавить тень, создается 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);
}
Вы можете управлять несколькими строками с помощью многомерного массива:)