前言:做相關(guān)demo動畫已經(jīng)有一段時間了、現(xiàn)在閑下來記錄下相關(guān)動畫制作工猜。iOS動畫主要就是路徑動畫米诉、幀動畫、縮放動畫篷帅、以及這些動畫的組合叫組合動畫史侣。另外還有一些3D動畫和轉(zhuǎn)場動畫拴泌。不想看原理的直接下載demo使用方式很簡單。
搖桿(手柄)制作
首先需要繪制搖桿的范圍我這畫了一個圓形惊橱、然后監(jiān)聽用戶的手勢蚪腐、根據(jù)手勢移動的前后位置判斷移動的方向上、下税朴、左回季、右。此外如果你規(guī)定用戶只能上下或者左右移動正林、不能斜角移動泡一、你可以根據(jù)移動的位置判斷當(dāng)前點和中心點這條直線的斜率偏移不能超過多少度。
效果如下:
handshank.gif
1.繪制背景邊界圓
CGContextRef context = UIGraphicsGetCurrentContext();
// CGContextSetRGBFillColor (context, 1, 0, 0, 1.0);//設(shè)置填充顏色
CGContextSetRGBStrokeColor(context,143/255.0,190/255.0,81/255.0,1.0);//畫筆線的顏色
CGContextSetLineWidth(context, 2.0);//線的寬度
bigRadius = LL_mmWidth(self)/2.0-4;
CGContextAddArc(context, LL_mmWidth(self)/2.0, LL_mmHeight(self)/2.0, bigRadius, 0, 2*PI, 0); //添加一個圓
CGContextDrawPath(context, kCGPathStroke); //繪制路徑
2.繪制中間搖桿圓和四個方向標志以及添加搖桿手勢監(jiān)聽觅廓。
-(void)createCenterCircle:(CGRect)selfFrame
{
//中間搖桿圓
_centerView = [[UIView alloc]init];
_centerView.frame = CGRectMake((CGRectGetWidth(selfFrame)-CGRectGetWidth(selfFrame)/3.0)/2.0, (CGRectGetHeight(selfFrame)-CGRectGetHeight(selfFrame)/3.0)/2.0, CGRectGetWidth(selfFrame)/3.0, CGRectGetHeight(selfFrame)/3.0);
_handShankOriginCenter = _centerView.center;
smallRadius = (CGRectGetWidth(selfFrame)/3.0)/2.0;
_centerView.layer.cornerRadius = smallRadius;
_centerView.layer.masksToBounds = YES;
_centerView.alpha = 0.8;
_centerView.backgroundColor = [UIColor colorWithRed:143/255.0 green:190/255.0 blue:81/255.0 alpha:1.0];
[self addSubview:_centerView];
//四個方向標志
float interval = (CGRectGetHeight(selfFrame)-LL_mmHeight(_centerView))/4.0;
for (int i = 0; i<4; i++) {
UIImageView *arrow = [self InsertImageView:self cgrect:CGRectMake(0, 0, 20*FIT_WIDTH, 12*FIT_WIDTH) image:[UIImage imageNamed:self.handShankArrows[i]]];
// InsertImageView(self, CGRectMake(0, 0, 20*FIT_WIDTH, 12*FIT_WIDTH), [UIImage imageNamed:self.handShankArrows[i]]);
// arrow.hidden = YES;//注意隱藏箭頭了
switch (i) {
case 0:
{
//上
arrow.center = CGPointMake(CGRectGetWidth(selfFrame)/2.0, interval);
}
break;
case 1:
//下
arrow.center = CGPointMake(CGRectGetWidth(selfFrame)/2.0, CGRectGetHeight(selfFrame)-interval);
break;
case 2:
//左
arrow.frame = CGRectMake(0, 0, 12*FIT_WIDTH, 20*FIT_WIDTH);
arrow.center = CGPointMake(interval, CGRectGetHeight(selfFrame)/2.0);
break;
case 3:
//右
arrow.frame = CGRectMake(0, 0, 12*FIT_WIDTH, 20*FIT_WIDTH);
arrow.center = CGPointMake(CGRectGetWidth(selfFrame)-interval, CGRectGetHeight(selfFrame)/2.0);
break;
default:
break;
}
}
//搖桿添加移動手勢
UIPanGestureRecognizer *pangesture = [[UIPanGestureRecognizer alloc]initWithTarget:self action:@selector(pangestureAction:)];
[_centerView addGestureRecognizer:pangesture];
}
3.分析手勢數(shù)據(jù)根據(jù)上一次移動的點和這次的做比較判斷移動方向
-(void)pangestureAction:(UIPanGestureRecognizer *)recognizer
{
CGPoint translation = [recognizer translationInView:self];
[recognizer setTranslation:CGPointZero inView:self];
CGPoint movingPosition = CGPointMake(recognizer.view.center.x + translation.x,
recognizer.view.center.y + translation.y);
int rangeRadius = bigRadius - smallRadius;
if ([self isInciclelPoint:movingPosition andR:rangeRadius centrePoing:_handShankOriginCenter]) {
_lasrtPoint = movingPosition;
_centerView.center = _lasrtPoint;
if (_lasrtPoint.y < _startPoint.y && (fabsf((float)(_lasrtPoint.y - _startPoint.y)) > fabs(_lasrtPoint.x - _startPoint.x))) {
//上
if (_currentDirection == HandShankDirectionUnknow) {
NSLog(@"開始上");
_currentDirection = HandShankDirectionStartTop;
}else{
NSLog(@"上");
_currentDirection = HandShankDirectionTop;
}
}else if (_lasrtPoint.y > _startPoint.y && (fabsf((float)(_lasrtPoint.y - _startPoint.y)) > fabs(_lasrtPoint.x - _startPoint.x)))
{
if (_currentDirection == HandShankDirectionUnknow) {
NSLog(@"開始下");
_currentDirection = HandShankDirectionStartDown;
}else{
NSLog(@"下");
_currentDirection = HandShankDirectionDown;
}
}else if (_lasrtPoint.x >_startPoint.x && (fabsf((float)(_lasrtPoint.x -_startPoint.x)) > fabsf((float)(_lasrtPoint.y -_lasrtPoint.y))) )
{
if (_currentDirection == HandShankDirectionUnknow) {
NSLog(@"開始右");
_currentDirection = HandShankDirectionStartRight;
}else{
NSLog(@"右");
_currentDirection = HandShankDirectionRight;
}
}else if (_lasrtPoint.x <_startPoint.x && (fabsf((float)(_lasrtPoint.x -_startPoint.x)) > fabsf((float)(_lasrtPoint.y -_lasrtPoint.y))) )
{
if (_currentDirection == HandShankDirectionUnknow) {
NSLog(@"開始左");
_currentDirection = HandShankDirectionStartLeft;
}else{
NSLog(@"左");
_currentDirection = HandShankDirectionLeft;
}
}
if (self.delegete && [self.delegete respondsToSelector:@selector(handShankDirectionDidChange:)]) {
[self.delegete handShankDirectionDidChange:_currentDirection];
}
}
if(recognizer.state == UIGestureRecognizerStateEnded || recognizer.state == UIGestureRecognizerStateCancelled || recognizer.state == UIGestureRecognizerStateFailed)
{
NSLog(@"結(jié)束");
_startPoint = _handShankOriginCenter;
[UIView animateWithDuration:0.5 animations:^{
_centerView.center = _handShankOriginCenter;
}];
_currentDirection = HandShankDirectionUnknow;
if (self.delegete && [self.delegete respondsToSelector:@selector(handShankDirectionDidEnd)]) {
[self.delegete handShankDirectionDidEnd];
}
}
}
餅狀圖繪制
前言:餅狀圖由三角弧組成鼻忠、弧線有起始角度和末尾角度組成、所以可以用一個mode類記錄相關(guān)信息杈绸。然后繪制三角弧帖蔓。效果如下:
pichart.gif
1.弧線貝塞爾路徑寫法
-(UIBezierPath *)bezierPathStartAngle:(CGFloat)startAngle endAngle:(CGFloat)endAngle
{
UIBezierPath *path = [UIBezierPath new];
[path moveToPoint:_centerPoint];
[path addArcWithCenter:_centerPoint radius:_radius startAngle:DEGREES_TO_RADIANS(startAngle) endAngle:DEGREES_TO_RADIANS(endAngle) clockwise:YES];
[path closePath];
return path;
}
2.生成弧線和對應(yīng)的文字
-(void)createPieChartView
{
[self.models enumerateObjectsUsingBlock:^(CurveModel * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
UIBezierPath *path = [self bezierPathStartAngle:obj.startAngel endAngle:obj.endAngel];
CAShapeLayer *trangleLayer = [CAShapeLayer layer];
// maskLayer.backgroundColor = [UIColor purpleColor].CGColor;
trangleLayer.path = [path CGPath];
trangleLayer.fillColor = obj.color.CGColor;
trangleLayer.fillRule = kCAFillRuleNonZero;//kCAFillRuleEvenOdd畫的區(qū)域 取反 解釋為奇偶。
[self.layer addSublayer:trangleLayer];
obj.trangleLayer = trangleLayer;
CGFloat angle = obj.endAngel-(obj.endAngel-obj.startAngel)/2.0;//扇形邊緣中心位置的角度
//扇形邊緣的中心點
// CGPoint aPoint = CGPointMake(_centerPoint.x+ _radius*cos(DEGREES_TO_RADIANS(angle)),_centerPoint.y+ _radius*sin(DEGREES_TO_RADIANS(angle)));
//外面邊緣的半徑
CGFloat outRadius = [self height]/2.0+100;//100是隨意
CGPoint outCenterPoint = CGPointMake(_centerPoint.x+ outRadius*cos(DEGREES_TO_RADIANS(angle)), _centerPoint.y+outRadius*sin(DEGREES_TO_RADIANS(angle)));
obj.outCenterPoint = outCenterPoint;
int width = 30;
//內(nèi)部邊緣文字
UILabel *label0 = [[UILabel alloc]init];
label0.adjustsFontSizeToFitWidth = YES;
label0.bounds = CGRectMake(0, 0, width, width);
CGFloat newRadius0 = (_radius-((width/2.0)/cos(DEGREES_TO_RADIANS(45))));//扇形的半徑+label的對角線長度
//新半徑扇形的邊緣中心點
CGPoint bPoint0 = CGPointMake(_centerPoint.x+ newRadius0*cos(DEGREES_TO_RADIANS(angle)), _centerPoint.y+newRadius0*sin(DEGREES_TO_RADIANS(angle)));
obj.innerLabelCenterPoint = bPoint0;
obj.innerLabe = label0;
label0.center = outCenterPoint;
label0.text = @"6";
label0.textAlignment = NSTextAlignmentCenter;
[self addSubview:label0];
//外圍邊緣文字
UILabel *label = [[UILabel alloc]init];
label.text = @"%10";
label.textAlignment = NSTextAlignmentCenter;
label.adjustsFontSizeToFitWidth = YES;
label.bounds = CGRectMake(0, 0, width, width);
CGFloat newRadius = (_radius+((width/2.0)/cos(DEGREES_TO_RADIANS(45))));//扇形的半徑+label的對角線長度
//新半徑扇形的邊緣中心點
CGPoint bPoint = CGPointMake(_centerPoint.x+ newRadius*cos(DEGREES_TO_RADIANS(angle)), _centerPoint.y+newRadius*sin(DEGREES_TO_RADIANS(angle)));
obj.outLabelCenterPoint = bPoint;
obj.outLabel=label;
label.center = outCenterPoint; //CGPointMake( aPoint.x+width/2.0, aPoint.y+((width/2.0)*tan(DEGREES_TO_RADIANS(angle))));
[self addSubview:label];
}];
}
3.添加簡單翻轉(zhuǎn)動畫和路徑動畫
-(void)startAnimation
{
//翻轉(zhuǎn) oglFlip
[CommonUse addAnimationLayer:self.layer type:@"oglFlip"];
[self.models enumerateObjectsUsingBlock:^(CurveModel * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
[self startLabelAnimation:obj];
}];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[self stopAnimation];
});
}
傳送門:
源碼
有疑問的小伙伴歡迎加交流討論QQ:206931384