I am trying to create an animated radial chart that looks like the activity app created by Apple. I provide an image to show what I would like as result:
Do you know how to obtain this result? If you have any idea could you please focus on the following points?
Create the gradient inside each circle
Create the shadow on the head of the circle
Thank you very much in advance.
Check out my custom control, I tried to make it as close as possible to the Activity app design, and everything is customizable.
https://github.com/maxkonovalov/MKRingProgressView
The basic idea behind the algorithm is quite simple.
To draw arc line with changing color:
Generate a conical gradient image
You can use a prerendered image from Photoshop or generate your own dynamically. I use a gradient image generator from here: https://github.com/maxkonovalov/MKGradientView.
Clip gradient image to show only the arc
CGContextSaveGState(ctx)
CGContextAddPath(ctx, arcPath)
CGContextClip(ctx)
CGContextDrawImage(ctx, gradientRect, gradientImage)
CGContextRestoreGState(ctx)
Drawing the shadow is even simpler:
Draw shadow behind your progress arc (shown with 50% opacity here)
I draw a circle shape matching arc's end for the shadow.
CGContextSetShadow(ctx, offset, shadowRadius)
CGContextAddPath(ctx, shadowPath)
CGContextSetFillColorWithColor(ctx, shadowColor)
CGContextFillPath(ctx)
Clip the shadow to fit into the progress circle
CGContextSaveGState(ctx)
CGContextAddPath(ctx, circlePath)
CGContextClip(ctx)
// Draw shadow...
CGContextRestoreGState(ctx)
And the final result looks like this:
This isn't quite what you need as it appears to generate the image for you, but you could get some good info from the source.
https://github.com/hmaidasani/RadialChartImageGenerator
Related
I'm trying to draw a rounded rectangle with transparency with the library Skia.
I get a perfect result if i'm using overlapping without transparency.
But when i'm using transparency, i get this:
That's what i get when i do not overlap:
Even if i modify the radius of the inner rectancle, there're still some overlaps/gabs.
My questitons:
What is the correct way to caluclate the radius of the inner rectangle, when i can accept some missplaced pixels?
Is there another way?
You can use saveLayerAlpha before drawing and then restore after drawing. This allows you to draw multiple paths, shapes, etc with a "global" alpha applied to the layer.
I was wondering if it was possible to change the color of a UIBezierPath strokeColor while its animating. For instance, if it goes past a certain angle like 45 deg, it changes from green to orange, and if it goes past 66 deg it goes from orange to red.
Somebody else suggested using a "gradual" (gradient) layer. If you can create a gradient that meets your needs then that would work.
You could do just about anything you want by creating an image that contains the colors you want, and then installing a shape layer as a mask layer to that image's layer, and animating changes to the path installed in the shape layer.
I've used a technique like that to create various sorts of "wipe" transitions that reveal an image. See the thread below for info and working code showing how to create a "Clock wipe", which is almost exactly what you need:
How do you achieve a "clock wipe"/ radial wipe effect in iOS?
I've used the CGContext based routine to fill a rectangle, but this time I actually want to fill all of a rectangle EXCEPT one part of it. I know this is possible in other drawing systems for other platofrm but can it be done with core graphics on iOS?
Both borderWidth and cornerRadius are animatable properties. So you could just animate them directly (using CABasicAnimation). In that rendering, you'd go from no border and no corners to having a border and corners in an animated way.
If you want to animate the rectangular tracing of the border, you'd need to use a CAShapeLayer (because the end of its path is animatable) and provide the illusion that way.
I want to fill specific color on specific area of an image.
EX:
In above Joker image, If touch on hair of Joker then fill specific color on hair Or touch on nose then fill specific color on nose.. etc. I hope may you understand what I am trying to say.
After googling it's may be achieve by use of UIBezierPath or CGContext Reference but I am very new for it, I tried to read this documentation but I do not understand (take more time) anything also I have limit of time for this Project. So I can not spend more time on it.
Also I found that we can use Flood fill algorithm. But I don't know how to use in my case.
NOTE: I don't want to divide original image (such like hair. nose, cap,...etc) because If I will do then there will be so many images in bundle so I need to handle it for both normal and retina device so this option is not helpful for me.
So please give me your valuable suggestion and also tell me which is best for me UIBezierPath or CGContext Reference? How can I fill color on specific portion of image? and/or can we fill color under the black border of area ? Because I am new at Quartz 2D Programming.
Use the Github library below. The post uses the flood fill algorithm : UIImageScanlineFloodfill
Objective C description : ObjFloodFill
If you want to look at detailed explanation of the algorithm : Recursion Explained with the Flood Fill Algorithm (and Zombies and Cats)
few of the other tutorials in other languages : Lode's Computer Graphics Tutorial : Flood Fill
Rather than attempting to flood fill an area of a raster-based image, a better approach (and much smaller amount of data) would be to create vector images. Once you have a vector image, you can stroke the outline to draw it uncolored, or you can fill the outline to draw it colored.
I recommend using CoreGraphics calls like CGContextStrokePath() and CGContextFillPath() to do the drawing. This will likely look better than using the flood fill because you will get nicely anti-aliased edges.
Apple has some good documentation on how to draw with Quartz 2D. Particularly the section on Paths is useful to what you're trying to do.
You can Clip the context based on image Alpha transparency
I have created a quick image with black color and alpha
Then using the below Code
- (void)drawRect:(CGRect)rect
{
CGContextRef context = UIGraphicsGetCurrentContext(); // Get the context
CGContextSetFillColorWithColor(context, [UIColor blueColor].CGColor); // Set the fill color to be blue
// Flip the context so that the image is not flipped
CGContextTranslateCTM(context, 0, rect.size.height);
CGContextScaleCTM(context, 1.0, -1.0);
// Clip the context by a mask created from the image
UIImage *image = [UIImage imageNamed:#"image.png"];
CGImageRef cgImage = image.CGImage;
CGContextClipToMask(context, rect, cgImage);
// Finally fill the context with the color and mask you set earlier
CGContextFillRect(context, rect);
}
The result
This is a quick hint of what you can do. However you need now to convert your image to add alpha transparent to the parts you need to remove
After a quick search I found these links
How can I change the color 'white' from a UIImage to transparent
How to make one colour transparent in UIImage
If You create your image as SVG vector base image, it will be very light (less than png, jpg) and really easy to manage via Quartz 2D using bezier paths. Bezier paths can be filled (white at starting). UIBezierPath have a method (containsPoint:) that help define if you click inside.
I have an icon image I would like to draw a 1px, colored 0.5 opacity line around, inside the image (similar to Stroke layer style with position:inside in Photoshop). So far I've tried this:
UIGraphicsBeginImageContextWithOptions(inCompositeSize, NO, inBaseImage.scale);
context = UIGraphicsGetCurrentContext();
CGContextDrawImage(context, frame, image.CGImage);
CGColorSpaceRef cs = CGColorSpaceCreateDeviceRGB();
CGContextSetStrokeColorSpace(context, cs);
CGColorSpaceRelease(cs);
CGContextSetStrokeColorWithColor(context, [UIColor blueColor].CGColor);
CGContextStrokePath(context);
//...
This seems to have no effect. I'm guessing this is because I'm working with an image and not a path. How can I produce an outline stroke effect on the image?
Clarification: I'm trying to draw an outline on the opaque icon area only. The icon background is 0 alpha.
StrokePath strokes a path, and you haven't plotted a path. That's why it strokes nothing.
You need to do either of two things:
Vectorize the raster image and stroke that path. Core Image's edge-detection filter will help, but even so, this is hard. There is no built-in API for this; you'll have to find a library that does it or do it yourself.
Fake it by drawing the image with a shadow. Note that shadows can be any color; it doesn't have to look like a shadow.