Overlapping loader circle

自古美人都是妖i 提交于 2019-12-04 13:57:53

This shows the general idea--transform is definitely the way to go. You'll have to adjust the sizes, arrows, and shadows for what you need. But the view allow the tint and angle to be adjusted from Interface Builder. This should get you going.

#import <UIKit/UIKit.h>
IB_DESIGNABLE

@interface ActivityCircleView : UIView

@property (nonatomic) IBInspectable CGFloat angleOfRotationInDegrees;

@end


#import "ActivityCircleView.h"

@implementation ActivityCircleView

- (void)setAngleOfRotation:(CGFloat)angleOfRotationInDegrees {
    _angleOfRotationInDegrees = angleOfRotationInDegrees;
    [self setNeedsDisplay];
}

- (void)drawRect:(CGRect)rect {
    [self drawActivityWithTintColor:self.tintColor angleOfRotationInDegrees:self.angleOfRotationInDegrees];
}

- (void)drawActivityWithTintColor: (UIColor*)tintColor angleOfRotationInDegrees: (CGFloat)angleOfRotationInDegrees
{
    //// General Declarations
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    CGContextRef context = UIGraphicsGetCurrentContext();

    //// Color Declarations
    CGFloat tintColorRGBA[4];
    [tintColor getRed: &tintColorRGBA[0] green: &tintColorRGBA[1] blue: &tintColorRGBA[2] alpha: &tintColorRGBA[3]];

    UIColor* brighter = [UIColor colorWithRed: (tintColorRGBA[0] * 0.5 + 0.5) green: (tintColorRGBA[1] * 0.5 + 0.5) blue: (tintColorRGBA[2] * 0.5 + 0.5) alpha: (tintColorRGBA[3] * 0.5 + 0.5)];

    //// Gradient Declarations
    CGFloat gradientLocations[] = {0, 0.73};
    CGGradientRef gradient = CGGradientCreateWithColors(colorSpace, (__bridge CFArrayRef)@[(id)tintColor.CGColor, (id)brighter.CGColor], gradientLocations);

    //// Shadow Declarations
    NSShadow* shadow = [[NSShadow alloc] init];
    [shadow setShadowColor: UIColor.blackColor];
    [shadow setShadowOffset: CGSizeMake(0.1, 0.1)];
    [shadow setShadowBlurRadius: 5];

    //// Activity Circle
    {
        //// Circle With Overlapping Shadow
        {
            CGContextSaveGState(context);
            CGContextTranslateCTM(context, 50, 50);
            CGContextRotateCTM(context, -angleOfRotationInDegrees * M_PI / 180);



            //// Left Half Circle Drawing
            UIBezierPath* leftHalfCirclePath = UIBezierPath.bezierPath;
            [leftHalfCirclePath moveToPoint: CGPointMake(0, -40)];
            [leftHalfCirclePath addCurveToPoint: CGPointMake(0, -20) controlPoint1: CGPointMake(0, -40) controlPoint2: CGPointMake(0, -31.68)];
            [leftHalfCirclePath addCurveToPoint: CGPointMake(-7.44, -18.57) controlPoint1: CGPointMake(-2.63, -20) controlPoint2: CGPointMake(-5.14, -19.49)];
            [leftHalfCirclePath addCurveToPoint: CGPointMake(-20, -0) controlPoint1: CGPointMake(-14.8, -15.62) controlPoint2: CGPointMake(-20, -8.42)];
            [leftHalfCirclePath addCurveToPoint: CGPointMake(0, 20) controlPoint1: CGPointMake(-20, 11.05) controlPoint2: CGPointMake(-11.05, 20)];
            [leftHalfCirclePath addCurveToPoint: CGPointMake(0, 40) controlPoint1: CGPointMake(0, 27.41) controlPoint2: CGPointMake(0, 34.35)];
            [leftHalfCirclePath addCurveToPoint: CGPointMake(-40, -0) controlPoint1: CGPointMake(-22.09, 40) controlPoint2: CGPointMake(-40, 22.09)];
            [leftHalfCirclePath addCurveToPoint: CGPointMake(-24.08, -31.94) controlPoint1: CGPointMake(-40, -13.05) controlPoint2: CGPointMake(-33.75, -24.64)];
            [leftHalfCirclePath addLineToPoint: CGPointMake(-23.84, -32.13)];
            [leftHalfCirclePath addCurveToPoint: CGPointMake(0, -40) controlPoint1: CGPointMake(-17.18, -37.07) controlPoint2: CGPointMake(-8.93, -40)];
            [leftHalfCirclePath addLineToPoint: CGPointMake(0, -40)];
            [leftHalfCirclePath closePath];
            [tintColor setFill];
            [leftHalfCirclePath fill];


            //// Circle With Shadow Drawing
            UIBezierPath* circleWithShadowPath = [UIBezierPath bezierPathWithOvalInRect: CGRectMake(-10, 20, 20, 20)];
            CGContextSaveGState(context);
            CGContextSetShadowWithColor(context, shadow.shadowOffset, shadow.shadowBlurRadius, [shadow.shadowColor CGColor]);
            [brighter setFill];
            [circleWithShadowPath fill];
            CGContextRestoreGState(context);



            //// Right Half Circle Drawing
            UIBezierPath* rightHalfCirclePath = UIBezierPath.bezierPath;
            [rightHalfCirclePath moveToPoint: CGPointMake(40, -0)];
            [rightHalfCirclePath addCurveToPoint: CGPointMake(0, 40) controlPoint1: CGPointMake(40, 22.09) controlPoint2: CGPointMake(22.09, 40)];
            [rightHalfCirclePath addCurveToPoint: CGPointMake(0, 20) controlPoint1: CGPointMake(0, 33.83) controlPoint2: CGPointMake(0, 27.02)];
            [rightHalfCirclePath addCurveToPoint: CGPointMake(20, -0) controlPoint1: CGPointMake(11.05, 20) controlPoint2: CGPointMake(20, 11.05)];
            [rightHalfCirclePath addCurveToPoint: CGPointMake(0, -20) controlPoint1: CGPointMake(20, -11.05) controlPoint2: CGPointMake(11.05, -20)];
            [rightHalfCirclePath addCurveToPoint: CGPointMake(0, -40) controlPoint1: CGPointMake(0, -28.3) controlPoint2: CGPointMake(0, -35.35)];
            [rightHalfCirclePath addCurveToPoint: CGPointMake(40, -0) controlPoint1: CGPointMake(22.09, -40) controlPoint2: CGPointMake(40, -22.09)];
            [rightHalfCirclePath closePath];
            CGContextSaveGState(context);
            [rightHalfCirclePath addClip];
            CGContextDrawLinearGradient(context, gradient, CGPointMake(20, -40), CGPointMake(20, 40), 0);
            CGContextRestoreGState(context);



            CGContextRestoreGState(context);
        }


        //// Arrow
        {
            //// Arrow Line Drawing
            UIBezierPath* arrowLinePath = UIBezierPath.bezierPath;
            [arrowLinePath moveToPoint: CGPointMake(43.5, 20.5)];
            [arrowLinePath addLineToPoint: CGPointMake(57.5, 20.5)];
            arrowLinePath.lineCapStyle = kCGLineCapRound;

            [UIColor.blackColor setStroke];
            arrowLinePath.lineWidth = 4;
            [arrowLinePath stroke];


            //// Arrow Head Drawing
            UIBezierPath* arrowHeadPath = UIBezierPath.bezierPath;
            [arrowHeadPath moveToPoint: CGPointMake(50.8, 14.5)];
            [arrowHeadPath addLineToPoint: CGPointMake(57.5, 20.5)];
            [arrowHeadPath addLineToPoint: CGPointMake(50.8, 26.5)];
            arrowHeadPath.lineCapStyle = kCGLineCapRound;

            [UIColor.blackColor setStroke];
            arrowHeadPath.lineWidth = 4;
            [arrowHeadPath stroke];
        }
    }


    //// Cleanup
    CGGradientRelease(gradient);
    CGColorSpaceRelease(colorSpace);
}


@end

By the way, I cheated a bit and used PaintCode.

Here's my attempt:

It's generated entirely in code (I had to use the Angle Gradient Layer to get the gradient, but the rest of the code is mine). I can easily obtain any desired angle just by applying a rotation transform:

Of course I also hard-coded all the values, because I was just trying it out, but feel free to play with it:

let con = UIGraphicsGetCurrentContext()
let c1 = UIColor(red: 0.8, green: 0.8, blue: 0.7, alpha: 1).CGColor
let c2 = UIColor(red: 0.8, green: 0.8, blue: 0.1, alpha: 1).CGColor
let outer:CGFloat = 20
let diff:CGFloat = 20
let inner:CGFloat = outer + diff
func circle(inset:CGFloat) {
    CGContextAddEllipseInRect(con, rect.rectByInsetting(
        dx: inset, dy: inset))
}

CGContextSaveGState(con)
circle(outer); circle(inner); CGContextEOClip(con)
let im = AngleGradientLayer.newImageGradientInRect(
    rect, colors:[c1,c2], locations:[0,1]).takeRetainedValue()
CGContextDrawImage(con, rect, im)
CGContextRestoreGState(con)

circle(outer)
CGContextStrokePath(con)
circle(inner)
CGContextStrokePath(con)

let (_,lower) = rect.rectsByDividing(rect.height / 2, fromEdge: .MinYEdge)
CGContextAddRect(con, lower)
CGContextEOClip(con)
CGContextSetFillColorWithColor(con, c1)

CGContextSaveGState(con)
CGContextSetShadowWithColor(con, CGSizeMake(0,3), 6, 
    UIColor.blackColor().colorWithAlphaComponent(0.7).CGColor)
let top = lower.origin.y - diff/2
let left = rect.width - diff * 2
circle(outer); circle(inner); CGContextEOClip(con)
CGContextFillEllipseInRect(con, CGRectMake(left,top,diff,diff))
CGContextRestoreGState(con)

CGContextStrokeEllipseInRect(con, CGRectMake(left,top,diff,diff))
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!