主要思路
1.CAShapeLayer + UIBezierPath
2.两个弧线的关系是个数学问题
我的实现是,月亮的两个端点连线作为内弧的圆半径,但感觉不是很漂亮,跟月亮实际有些偏离。希望有朋友有更好方法。
3.难点在计算,内弧圆的圆心和半径,画画图结合点数学基础就OK了。
//
// ViewController.m
// MoonProgressDemo
//
// Created by Robin on 2019/8/4.
// Copyright © 2019 RobinCompany. All rights reserved.
//
#import "ViewController.h"
@interface ViewController ()
@property (nonatomic, strong) CAShapeLayer *moonLayer;
@property (nonatomic, assign) CGFloat progress;
@property (weak, nonatomic) IBOutlet UISlider *slider;
@end
@implementation ViewController
#define ScreenW CGRectGetWidth([UIScreen mainScreen].bounds)
#define ScreenH CGRectGetHeight([UIScreen mainScreen].bounds)
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
[self addLayer];
_slider.layer.anchorPoint = CGPointMake(1, 1);
_slider.transform = CGAffineTransformMakeRotation(- M_PI_2);
}
- (void)addLayer {
CAShapeLayer *moon = [CAShapeLayer layer];
CGFloat quardW = 0.25 * ScreenW;
moon.frame = CGRectMake(quardW, 0.25 * ScreenH, 2 * quardW, 2 * quardW);
_moonLayer = moon;
// _moonLayer.backgroundColor = [UIColor redColor].CGColor;
[self.view.layer addSublayer:moon];
moon.strokeColor = [UIColor redColor].CGColor;
moon.fillColor = nil;
CGFloat x0 = 0.5 * CGRectGetWidth(_moonLayer.bounds);
CGFloat y0 = 0.5 * CGRectGetHeight(_moonLayer.bounds);
CGPoint center = CGPointMake(x0, y0);
CGFloat radius = 0.5 * CGRectGetWidth(_moonLayer.bounds);
CGFloat startAngle = 0.f;
CGFloat endAngle = - M_PI;
UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:center radius:radius startAngle:startAngle endAngle:endAngle clockwise:YES];
// moon.path = path.CGPath;
CGPoint center1 = CGPointMake(x0, y0 - radius / (tan(M_PI / 6.0f)));
UIBezierPath *path1 = [UIBezierPath bezierPathWithArcCenter:center1 radius:2.0f * radius startAngle:2.0f * M_PI / 3.0f endAngle:M_PI / 3.0f clockwise:NO];
// [path addArcWithCenter:center1 radius:2 * radius startAngle:4 * M_PI / 3 endAngle:5 * M_PI / 3 clockwise:NO];
[path appendPath:path1];
moon.path = path.CGPath;
}
- (IBAction)sliderSlide:(UISlider *)sender {
self.progress = sender.value;
_moonLayer.fillColor = [UIColor colorWithRed:0 green:0 blue:255 alpha:_progress].CGColor;
// _moonLayer.anchorPoint
_moonLayer.affineTransform = CGAffineTransformMakeRotation(_progress * M_PI / 6.0f);
}
- (void)setProgress:(CGFloat)progress {
_progress = progress;
CGFloat endAngle1 = (1.0f + progress) * M_PI;
CGFloat x0 = 0.5 * CGRectGetWidth(_moonLayer.bounds);
CGFloat y0 = 0.5 * CGRectGetHeight(_moonLayer.bounds);
CGPoint center = CGPointMake(x0, y0);
CGFloat radius = 0.5 * CGRectGetWidth(_moonLayer.bounds);
UIBezierPath *path1 = [UIBezierPath bezierPathWithArcCenter:center radius:radius startAngle:0.f endAngle:endAngle1 clockwise:YES];
CGFloat r2 = 2.0f * cos(0.5 * progress * M_PI) * radius;
CGFloat startAngle2 = (0.5 * progress + 2.0f / 3.0f) * M_PI;
CGFloat endAngle2 = (0.5 * progress + 1.0f / 3.0f) * M_PI;
CGFloat distance = radius * sin (0.5 * progress *M_PI) + r2 * cos(M_PI / 6);
CGFloat deltaX = distance * sin(0.5 * progress * M_PI);
CGFloat deltaY = distance * cos(0.5 * progress * M_PI);
CGPoint center2 = CGPointMake(x0 + deltaX, y0 - deltaY);
UIBezierPath *path2 = [UIBezierPath bezierPathWithArcCenter:center2 radius:r2 startAngle:startAngle2 endAngle:endAngle2 clockwise:NO];
[path1 appendPath:path2];
_moonLayer.path = path1.CGPath;
}
@end