2012-06-22 12 views
6

Tengo problemas para implementar "Efectos de Relieve/Sombra" en mi dibujo. funcionalidad pintura de dedos está trabajando bien con mi costumbre UIView y por debajo es mi código drawRect método:Cómo crear efectos en relieve o en la sombra con Core Graphics (para pintura de dedos)

Edición de código con todos los métodos:

- (void)drawRect:(CGRect)rect 
{ 
    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); 
    CGContextSaveGState(context); 

    // for shadow effects 
    CGContextSetShadowWithColor(context, CGSizeMake(0, 2),3, self.lineColor.CGColor); 
    CGContextStrokePath(context); 
    [super drawRect:rect]; 
} 

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]; 
} 

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

} 

cuando he implementado este estoy consiguiendo efectos de pintura con puntos dot dot ...

Vea a continuación la imagen (que no tiene sombras ni efectos en relieve). Si tienes alguna idea de cómo agregar estos efectos, por favor dame alguna sugerencia. ¿Cómo puedo resolver esto?

enter image description here

Respuesta

4

Parece que va a crear cientos, quizás miles de caminos separados, uno en cada drawRect. Usted aplana estos usando [self.layer renderInContext], pero no creo que sea una buena forma de hacerlo. En cambio, creo que lo que quieres hacer es crear un UIBezierPath para seguir el dedo, agregar rutas a eso y dibujar UIBezierPath en la pantalla. Si crea dos capas (o vistas) puede configurar la superior (transparente) para "dibujar". Cuando el usuario levanta su dedo, entonces renderiza todo UIBezierPath en la segunda capa (junto con los datos dibujados previamente) y crea una nueva UIBezierPath para dibujar el siguiente seguimiento de dedo. De esta forma, solo está actualizando una capa (la superior) cuando rastrea el dedo de otra persona. Esto ayudará a evitar que el dispositivo se ralentice dibujando demasiados caminos.

Aunque, diré, su método actual produce un efecto de aspecto "3D".

+0

apreciamos su sugerencia. He usado UIBezierPath y lo he implementado, pero nos enfrentamos a un problema como la funcionalidad de borrar y elegir diferentes colores de pintura ... así que finalmente he cambiado la funcionalidad y uso CGContext. ahora toda la funcionalidad, como Borrar, cambiar el color del pincel está funcionando bien. El problema es solo para crear Relieve o efectos de sombras. que los efectos no funcionan correctamente ... la línea recta funciona bien con efectos de sombra. Pero los efectos de curva (suave) no funcionan bien. Por favor dígame alguna sugerencia usando CGContext. – Hitarth

+0

Pregunta rápida: ¿Cómo desea que funcione Erase? La mayoría de los programas de 'dibujo' borrarán cada 'ruta' separada (como se define como un toque de un dedo/evento de arrastrar/finalizar). Esto funciona con mi sugerencia/respuesta. Sin embargo, si intenta borrar cada punto de ruta o incluso cada píxel ... eso será mucho más difícil de lograr. –

+0

estoy borrando usando el contexto actual. y funciona bien – Hitarth

0

No estoy seguro sobre el relieve, pero si lo que desea es aplicar una sombra paralela a un dibujo que se actualiza progresivamente, entonces un buen enfoque sería usar CALayers (link to a tutorial). Básicamente, su dibujo progresivo actualizaría una imagen transparente (sin intentar dibujar ninguna sombra en esta imagen) y esta imagen se configuraría para mostrarse con una sombra paralela a través de su CALayer.

0

La sombra se crea en los bordes y se dibujan pequeños segmentos de líneas y esto crea este efecto. Necesitas crear un camino y luego acariciarlo una vez. Este código podría ayudarle :)

for (int i=0; i<[currentPath count]; i++) 
{ 
    CGPoint mid1 = [[self midPoint:[currentPath objectAtIndex:i+1] :[currentPath objectAtIndex:i]] CGPointValue]; 
    CGPoint mid2 = [[self midPoint:[currentPath objectAtIndex:i+2] :[currentPath objectAtIndex:i+1]] CGPointValue]; 
    CGContextMoveToPoint(context, mid1.x, mid1.y); 
    CGContextAddQuadCurveToPoint(context, [[currentPath objectAtIndex:i+1] CGPointValue].x, [[currentPath objectAtIndex:i+1] CGPointValue].y, mid2.x, mid2.y); 
    CGContextSetShadow(context, CGSizeMake(-2, -2), 3); 

    CGContextSetLineCap(context, kCGLineCapRound); 
    CGContextSetStrokeColorWithColor(context,[color CGColor]);    
    CGContextSetLineWidth(context, linewidth);    

    i+=2; 
} 
CGContextStrokePath(context); 

probar este camino .. Esto resolvió podría resolver su problema .. En primer lugar crear ur camino y después de que esté completamente creado, acariciarlo. Esto sucede porque en cada línea pequeña que tocas y por lo tanto la sombra creada hace un punto en sus límites, entonces obtienes este efecto.

+0

¿Qué es CurrntPath en su código y por qué está usando loop? sin conseguir ... por favor vea mi código fuente completo (editado). – Hitarth

+0

Estoy creando una matriz de puntos, la ruta actual es esa matriz. Esta matriz se crea con puntos, mirando desde el toque hasta el final :) – DivineDesert

Cuestiones relacionadas