Easing圆环动画
效果
源码
https://github.com/YouXianMing/Animations
//
// CircleView.h
// YXMWeather
//
// Created by XianMingYou on 15/11/12.
// Copyright (c) 2015年 XianMingYou. All rights reserved.
//
#import <UIKit/UIKit.h>
#import "YXEasing.h"
@interface CircleView : UIView
/**
* 线条宽度
*/
@property (nonatomic) CGFloat lineWidth;
/**
* 线条颜色
*/
@property (nonatomic, strong) UIColor *lineColor;
/**
* 旋转方向
*/
@property (nonatomic) BOOL clockWise;
/**
* 开始角度
*/
@property (nonatomic) CGFloat startAngle;
/**
* 初始化view
*/
- (void)buildView;
/**
* 做strokeEnd动画
*
* @param value 取值 [0, 1]
* @param func 函数指针
* @param animated 是否执行动画
* @param duration 动画持续的时间
*/
- (void)strokeEnd:(CGFloat)value animationType:(AHEasingFunction)func animated:(BOOL)animated duration:(CGFloat)duration;
/**
* 做strokeStart动画
*
* @param value 取值 [0, 1]
* @param func 函数指针
* @param animated 是否执行动画
* @param duration 动画持续的时间
*/
- (void)strokeStart:(CGFloat)value animationType:(AHEasingFunction)func animated:(BOOL)animated duration:(CGFloat)duration;
/**
* 便利构造器创建出实例对象
*
* @param frame frame值
* @param width 线条宽度
* @param color 线条颜色
* @param clockWise 是否是顺时钟
* @param angle 开始是否的角度(取值范围 0° ~ 360°)
*
* @return 实例对象
*/
+ (instancetype)circleViewWithFrame:(CGRect)frame
lineWidth:(CGFloat)width
lineColor:(UIColor *)color
clockWise:(BOOL)clockWise
startAngle:(CGFloat)angle;
@end
//
// CircleView.m
// YXMWeather
//
// Created by XianMingYou on 15/11/12.
// Copyright (c) 2015年 XianMingYou. All rights reserved.
//
#import "CircleView.h"
// 将度数转换为弧度
#define RADIAN(degrees) ((M_PI * (degrees))/ 180.f)
// 将弧度转换为度数
#define DEGREES(radian) ((radian) * 180.f / M_PI)
@interface CircleView ()
/**
* 圆形layer
*/
@property (nonatomic, strong) CAShapeLayer *circleLayer;
@end
@implementation CircleView
/**
* 初始化frame值
*
* @param frame 尺寸值
*
* @return 实例对象
*/
- (instancetype)initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) {
// 创建出layer
[self createCircleLayer];
}
return self;
}
/**
* 创建出layer
*/
- (void)createCircleLayer {
self.circleLayer = [CAShapeLayer layer];
self.circleLayer.frame = self.bounds;
[self.layer addSublayer:self.circleLayer];
}
/**
* 初始化view
*/
- (void)buildView {
// 初始化信息
CGFloat lineWidth = (self.lineWidth <= 0 ? 1 : self.lineWidth);
UIColor *lineColor = (self.lineColor == nil ? [UIColor blackColor] : self.lineColor);
CGSize size = self.bounds.size;
CGFloat radius = size.width / 2.f - lineWidth / 2.f; // 设置半径(刚好贴到frame上面去)
// 旋转方向
BOOL clockWise = self.clockWise;
CGFloat startAngle = 0;
CGFloat endAngle = 0;
if (clockWise == YES) {
startAngle = -RADIAN(180 - self.startAngle);
endAngle = RADIAN(180 + self.startAngle);
} else {
startAngle = RADIAN(180 - self.startAngle);
endAngle = -RADIAN(180 + self.startAngle);
}
// 创建出贝塞尔曲线
UIBezierPath *circlePath \
= [UIBezierPath bezierPathWithArcCenter:CGPointMake(size.height / 2.f, size.width / 2.f)
radius:radius
startAngle:startAngle
endAngle:endAngle
clockwise:clockWise];
// 获取path
self.circleLayer.path = circlePath.CGPath;
// 设置颜色
self.circleLayer.strokeColor = lineColor.CGColor;
self.circleLayer.fillColor = [[UIColor clearColor] CGColor];
self.circleLayer.lineWidth = lineWidth;
self.circleLayer.strokeEnd = 0.f;
}
- (void)strokeEnd:(CGFloat)value animationType:(AHEasingFunction)func animated:(BOOL)animated duration:(CGFloat)duration {
// 过滤掉不合理的值
if (value <= 0) {
value = 0;
} else if (value >= 1) {
value = 1.f;
}
if (animated) {
// 关键帧动画
CAKeyframeAnimation *keyAnimation = [CAKeyframeAnimation animation];
keyAnimation.keyPath = @"strokeEnd";
keyAnimation.duration = duration;
keyAnimation.values = \
[YXEasing calculateFrameFromValue:self.circleLayer.strokeEnd
toValue:value
func:func
frameCount:duration * 60];
// 执行动画
self.circleLayer.strokeEnd = value;
[self.circleLayer addAnimation:keyAnimation forKey:nil];
} else {
// 关闭动画
[CATransaction setDisableActions:YES];
self.circleLayer.strokeEnd = value;
[CATransaction setDisableActions:NO];
}
}
- (void)strokeStart:(CGFloat)value animationType:(AHEasingFunction)func animated:(BOOL)animated duration:(CGFloat)duration {
// 过滤掉不合理的值
if (value <= 0) {
value = 0;
} else if (value >= 1) {
value = 1.f;
}
if (animated) {
// 关键帧动画
CAKeyframeAnimation *keyAnimation = [CAKeyframeAnimation animation];
keyAnimation.keyPath = @"strokeStart";
keyAnimation.duration = duration;
keyAnimation.values = \
[YXEasing calculateFrameFromValue:self.circleLayer.strokeStart
toValue:value
func:func
frameCount:duration * 60];
// 执行动画
self.circleLayer.strokeStart = value;
[self.circleLayer addAnimation:keyAnimation forKey:nil];
} else {
// 关闭动画
[CATransaction setDisableActions:YES];
self.circleLayer.strokeStart = value;
[CATransaction setDisableActions:NO];
}
}
+ (instancetype)circleViewWithFrame:(CGRect)frame
lineWidth:(CGFloat)width
lineColor:(UIColor *)color
clockWise:(BOOL)clockWise
startAngle:(CGFloat)angle {
CircleView *circleView = [[CircleView alloc] initWithFrame:frame];
circleView.lineWidth = width;
circleView.lineColor = color;
circleView.clockWise = clockWise;
circleView.startAngle = angle;
return circleView;
}
@end
细节