问题
I wonder if is possible to animate the fill color of a path I have drawn using CoreGraphics? I am drawing this: Simple drawing with Quartz - Core Graphics
and I want to change its fill color from white to let's say gray. Is this possible?
I know the existence of view.layer.content property but Is this useful here? Though, I am not sure how can I use it in this case.
Thanks in advance.
Update
I am trying this approach (its buggy, hence I can tell if its going to work) basically I am creating a CGImageRef and pass it to self.layer.contents which is animatable using UIView animations but .... I am getting strange results, besides is not animating.
int bitsPerComponent = 8;
int channels = 4;
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
void *data = malloc(self.bounds.size.width*self.bounds.size.height*channels);
CGContextRef context = CGBitmapContextCreate(data, //pointer to data
self.bounds.size.width, //width
self.bounds.size.height, //height
bitsPerComponent, //bitsPerComponent
self.bounds.size.width*channels,//bytesPerRow
colorSpace, //colorSpace
kCGImageAlphaPremultipliedFirst); //bitmapInfo
//method that uses below link's code
[self _drawBackgroundInContext:context color:UIColorFromMandalaBoxType(type)];
CGDataProviderRef dataProvider = CGDataProviderCreateWithData(NULL, //info, NULL
data, //pointer to data
self.bounds.size.width*self.bounds.size.height*channels, //number of bytes
NULL); //release callback
CGImageRef image = CGImageCreate(self.bounds.size.width, //width
self.bounds.size.height, //height
bitsPerComponent, //bitsPerComponent
bitsPerComponent*channels, //bitsPerPixel
self.bounds.size.width*channels, //bytesPerRow
colorSpace, //colorSpace
kCGImageAlphaPremultipliedFirst, //bitmapInfo
dataProvider, NULL, false, kCGRenderingIntentDefault);
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:1.5f];
self.layer.contents = (id)image;
[UIView commitAnimations];
CGImageRelease(image);
CGDataProviderRelease(dataProvider);
CGContextRelease(context);
free(data);
CGColorSpaceRelease(colorSpace);
Is logic OK?, and where is the mistake here? ;(
回答1:
Edited answer:
You can't animate stuff in -drawRect:
. If you're trying to animate the color of a shape, you may want to look at CAShapeLayer
. It allows you to specify a CGPathRef
that it should draw, as well as stroke/fill colors, and all these properties are animatable. One thing to bear in mind, though, is that this isn't terribly efficient at its job. If your shape is not animating all the time, you may want to set shouldRasterize
to YES
. This will significantly speed up the rendering as long as the layer is not animating. If you do this, be careful as there are bugs relating to shouldRasterize
. One that springs to mind is if you set the opacity
to 0, and later make it non-0, shouldRasterize
has a tendency to draw nothing at all because it cached the drawing at the 0 opacity.
Original answer:
If you're living in CoreGraphics entirely, you can use CGContextSetFillColorWithColor()
, giving it the context and a CGColorRef (e.g. CGContextSetFillColorWithColor(ctx, [UIColor grayColor].CGColor)
. If you're trying to adjust the fill color of the "current" graphics context, you can also just use the slightly simpler [[UIColor grayColor] setFill]
.
Edit: After looking at your link, you just need to change the line that says
CGContextSetFillColorWithColor(context, [UIColor white].CGColor);
to use whatever color you want. In this case it would be
CGContextSetFillColorWithColor(context, [UIColor grayColor].CGColor);
回答2:
I don't think you can. Quartz is meant for drawing static things like buttons, it's not good at real-time drawing.
回答3:
You might look at CALayer and Core Animation. You might be able to do something like this (untested):
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration: 0.8];
self.view.layer.backgroundColor = [UIColor grayColor];
[UIView commitAnimations];
CALayer's backgroundColor is "animatable". This might require some changes to your drawRect: method - like doing a fill with [UIColor clearColor] and/or setting view's opaque property to NO, etc.
Just an idea - but it should be doable.
I had to do something similar but a bit more involved. For that I ended up using a second thread and a kind of Producer/Consumer pattern. I think that that would overkill for your needs, but it is another option.
来源:https://stackoverflow.com/questions/4129127/how-to-animate-fill-color-of-path-drawn-with-cgcontextdrawpath-etc-in-drawrect