2012-06-20 3 views
10

Используя основную графику, я пытаюсь нарисовать линию, в которой, когда я пытаюсь добавить тень, создается 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

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

ответ

8

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

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

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

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

Update

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

Update 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; 
} 
+0

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

+1

Достаточно честный. Когда пользователь перемещает палец, создавая общий ход, записывается серия точек (каждый цикл цикла цикла). Вы, по-видимому, только записываете предыдущую и текущую точку для записи в ваш новый 'UIImage'. Вместо этого консолидируйте все точки, созданные между сообщением 'touchhesBegan: withEvent:' и сообщением 'touchhesEnded: withEvent:', преобразуйте их в путь (либо CGPath, либо UIBezierPath) ** после ** пользователь поднял палец ('touchesEnded: withEvent:') и передать полный штрих вашему новому 'UIImage'. Замечания @ relikd о прозрачных слоях тоже хороши. – gschandler

+0

Спасибо за помощь в коде, ваш код правильный, но он создаст чертеж на сенсорном конце. И мне нужно нарисовать линию с движением пальца пользователя. Поэтому я пытаюсь изменить код, и пусть вы знаете, что такое результат. –

4

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

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

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

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

2

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

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

-(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); 

} 

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

+0

Привет, Димпл, Спасибо за ответ, но код становится разбитым на цикл, точка середины 2, значение индекса звучит, чтобы иметь какую-то логическую проблему. Когда я попытался с отладкой, он потерпел аварию в [pointArray objectAtIndex: i + 2], поскольку в этом индексе не было объекта, пожалуйста, поделитесь тем, как эта часть работает! –

+0

добавьте i + = 2 в цикл, так как мы используем по 4 пункта за раз, нам это нужно. – DivineDesert

Смежные вопросы