iOS旋钮动画-CircleKnob
- 欢迎相同喜欢动效的project师/UI设计师/产品添加我们
- iOS动效特攻队–>QQ群:547897182
- iOS动效特攻队–>熊熊:648070256
前段时间和群里的一个设计师配合。依据网上的一个旋钮gif为原型,用代码做出来了。先来看下原型的效果
在看下以下是我做完后成品的效果,加了一个通过移动光源来对阴影控制的效果。这样看起来更立体点。
(那个太阳有点不协调。
。
。)
同一时候附上代码链接https://git.oschina.net/BearXR/CircleKnob
还有单独的下载包http://download.csdn.net/detail/xiongbaoxr/9419655
以下開始简单的解说下构思步骤和部分代码片段
1,构建底盘
首先我们要构造两个圆盘和旋钮上的红点
用view画两个圆盘,和一个小的红色控制点。
注意:红色的控制点我又单独新建了一个view,这样方便待会做手势控制。从而不会影响到后面的view。而且全部view的圆心都要设置好。后面和角度相关的处理会非常多的。最好能准确和self.view或者window能有直接的关联。
2。底盘添加点击和拖动的手势
在这里我们要添加手势,还有起始点,终点的角度。
我画了辅助线,便于调试。
手势和过渡效果都写好了。所以效果我就直接放上来了。
3,添加外围的扇环
因为后面要做阴影,所以除了扇环的底色和效果是用了一个view,其余的每一个小格子我都是新开了一个view,而且将旋钮的圆心位置设置为锚点进行旋转。
#pragma mark - 设置外围的扇环形
- (void)initSetFanView
{
CGFloat delta_distance = 26;
fanView = [[FanView alloc] initWithFrame:CGRectMake(0, 0, knob_width + delta_distance * 2, knob_width + delta_distance * 2)];
fanView.center = knob.center;
fanView.backgroundColor = [UIColor clearColor];
fanView.userInteractionEnabled = NO;
[self.view addSubview:fanView];
fanView.knobValue = -startAngleValue;//设置起始点
fanView.lightSource_InWindow = lightSource;
}
- (void)drawRect:(CGRect)rect
{
contextBack = UIGraphicsGetCurrentContext();
contextFore = UIGraphicsGetCurrentContext();
[self drawFan:contextBack
bezierPath:bezierPathBack
knobAngle:180 + endAngleValue
strokeColor:[UIColor colorWithRed:202/255.0 green:207/255.0 blue:202/255.0 alpha:1.0f]];
[self drawFan:contextFore
bezierPath:bezierPathFore
knobAngle:_knobValue
strokeColor:[UIColor colorWithRed:174/255.0 green:0/255.0 blue:0/255.0 alpha:1.0f]];
}
// 绘制扇形
- (void)drawFan:(CGContextRef)context bezierPath:(UIBezierPath *)bezierPath knobAngle:(CGFloat)knobAngle strokeColor:(UIColor *)strokeColor
{
CGRect frame = self.frame;
CGFloat radius = (CGRectGetWidth(frame) - lineWidth) / 2;
CGFloat angleForOne = M_PI / 180.0f;
CGFloat circleLength = radius * 2 * M_PI;
int gapCount = fanShowCount - 1; //间隙个数
CGFloat gapWidth = 5; //间隙距离
// 计算须要绘制的角度(角度制)
knobAngle = knobAngle < -startAngleValue ? -startAngleValue : knobAngle;
knobAngle = knobAngle > 180 + endAngleValue ? 180 + endAngleValue : knobAngle;
// 设置弧线路径
bezierPath = [UIBezierPath bezierPathWithArcCenter:CGPointMake(CGRectGetWidth(frame)/2, CGRectGetHeight(frame)/2) radius:(CGRectGetWidth(frame) - lineWidth)/2.0 startAngle:angleForOne * (180 - startAngleValue) endAngle:angleForOne * (180 + knobAngle) clockwise:YES];
CGContextAddPath(context, bezierPath.CGPath);
// 设置线的颜色。线宽,接头样式
CGContextSetStrokeColorWithColor(context, strokeColor.CGColor);
CGContextSetFillColorWithColor(context, [UIColor clearColor].CGColor);
CGContextSetLineWidth(context, lineWidth);
CGContextSetLineCap(context, kCGLineCapButt);
// 绘制虚线
CGFloat drawLineLength = circleLength * (1- (startAngleValue + endAngleValue)/fullAngleValue);
CGFloat showLineLengthPer = (drawLineLength - gapWidth * gapCount)/(fanShowCount - 1);
CGFloat lengths[2] = {showLineLengthPer,gapWidth};
CGContextSetLineDash(context, 0, lengths, 2);
CGContextDrawPath(context, kCGPathFillStroke);//最后一个參数是填充类型
if (!self.blockViewArray) {
self.blockViewArray = [[NSMutableArray alloc] init];
}
// 绘制小方格view(而且仅仅绘制一次)
static BOOL drawBlock = NO;
if (!drawBlock) {
drawBlock = YES;
for (int i = 1; i < fanShowCount; i++) {
CGFloat blockWidth = lineWidth + 8;
CGFloat blockHeight = 5;
CGFloat block_x = CGRectGetWidth(frame) / 2 - radius - blockWidth/2;
CGFloat block_y = CGRectGetHeight(frame) / 2;
// 角度修正
if (blockHeight > gapWidth) {
block_y = block_y - blockHeight/2;
}else{
block_y = block_y + (gapWidth - blockHeight)/2;
}
// 方格view 可辅助绘制垂直平分线
ViewWithAutoShadow *viewBlock = [[ViewWithAutoShadow alloc] initWithFrame:CGRectMake(block_x, block_y, blockWidth, blockHeight)];
viewBlock.showAssistPoint = NO;
viewBlock.backgroundColor = [UIColor colorWithRed:248/255.0 green:238/255.0 blue:237/255.0 alpha:1.0f];
[self addSubview:viewBlock];
// 依据锚点旋转
CGFloat blockAngle = (180 + startAngleValue + endAngleValue)/fanShowCount*i - startAngleValue;
CGAffineTransform rotate = GetCGAffineTransformRotateAroundPoint1(viewBlock.center.x, viewBlock.center.y, CGRectGetWidth(frame)/2, CGRectGetHeight(frame)/2, blockAngle/180.0 * M_PI);
[viewBlock setTransform:rotate];
AppDelegate *myDelegate = [[UIApplication sharedApplication] delegate];
[viewBlock drawShadowEffectWithSourcePoint:_lightSource_InWindow assistInView:myDelegate.window];
[self.blockViewArray addObject:viewBlock];
}
}
}
4,添加动画效果
给底盘和扇环都添加动效。里面用了定时器。关于定时器能够看參考这篇博客http://blog.csdn.net/xiongbaoxr/article/details/50580701
动效的代码片段
// 运行动画
- (void)changeRadiusWithAnimation:(CGFloat)radius lastRadius:(CGFloat)lastRadius duration:(CGFloat)duration
{
CGFloat countAll = ABS(radius - lastRadius);
double delaySeconds = 0.001f;
CGFloat animateCount = duration/delaySeconds;
__block int i = 0;
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
dispatch_source_set_timer(timer, DISPATCH_TIME_NOW, delaySeconds * NSEC_PER_SEC, 0);
dispatch_source_set_event_handler(timer, ^{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
if (i >= animateCount) {
dispatch_source_cancel(timer);
}else{
i ++;
dispatch_sync(dispatch_get_main_queue(), ^{
// 扇环进度条动画
CGFloat anglePer = countAll/animateCount * i;
int k = radius > lastRadius ?
anglePer : -anglePer;
CGFloat needValue = lastRadius + k;
fanView.knobValue = needValue;
// 该方法会又一次调用drawRect方法
[fanView setNeedsDisplay];
// 旋钮转动
knob.transform = CGAffineTransformMakeRotation((needValue/180.0 - 0) * M_PI);
});
}
});
});
dispatch_resume(timer);
}
5。最后一步是处理阴影效果,里面涉及的东西比較多。
不详解代码,说一下思路。关于阴影处理的主要是这个类 ViewWithAutoShadow.h
5.1,首先我们设置一个光源点,这个小太阳就是我们的光源所在的位置
5.2,为了便于调试和理解,我对全部须要做投影效果的view画出了其与光源的连线,view的垂直平分线。而且进行了对应的延长。
同一时候也把view的四个顶点和中心点也描出来了
5.3。注意看,每一个夹脚处都有一个小的出头部分。这就是阴影的偏移量。
依照这个偏移量来设置阴影就会有一种仿真的效果。
5.4,我们把阴影效果设置上去看下终于的效果,是不是開始有点感觉了?
5.5最后把全部的辅助线都关掉。再看看效果
6,先就这么多。花了好几个晚上做出来的。想弄清原理的话主要还是在代码里面。代码凝视写的也比較多。
欢迎有兴趣做动效的私聊我啊。纯粹是兴趣,不为不论什么利益。
iOS旋钮动画-CircleKnob的更多相关文章
- iOS核心动画学习整理
最近利用业余时间终于把iOS核心动画高级技巧(https://zsisme.gitbooks.io/ios-/content/chapter1/the-layer-tree.html)看完,对应其中一 ...
- IOS 核心动画之CAKeyframeAnimation - iBaby
- IOS 核心动画之CAKeyframeAnimation - 简单介绍 是CApropertyAnimation的子类,跟CABasicAnimation的区别是:CABasicAnimation ...
- iOS各种动画效果
ios各种动画效果 最普通动画: //开始动画 [UIView beginAnimations:nil context:nil]; //设定动画持续时间 [UIView setAnimationDu ...
- IOS之动画
IOS之动画 15.1 动画介绍 15.2 Core Animation基础 15.3 隐式动画 15.4 显式动画 15.5 关键帧显式动画 15.6 UIView级别动画 15.1 动画介绍 ...
- IOS 动画专题 --iOS核心动画
iOS开发系列--让你的应用“动”起来 --iOS核心动画 概览 通过核心动画创建基础动画.关键帧动画.动画组.转场动画,如何通过UIView的装饰方法对这些动画操作进行简化等.在今天的文章里您可以看 ...
- ios 学习动画的套路 (一)
你也肯定喜欢炫酷的动画! 在APP中,动画就是一个点睛之笔!可以给用户增加一些独特的体验感,估计也有许多的和我一样的,看着那些觉得不错的动画,也就只能流口水的孩子,毕竟~不知道从哪里下手去写!会连续的 ...
- Bodymovin:Bodymovin和Lottie:把AE动画转换成HTML5/Android/iOS原生动画
转自:https://www.cnblogs.com/zamhown/p/6688369.html 大杀器Bodymovin和Lottie:把AE动画转换成HTML5/Android/iOS原生动画 ...
- 大杀器Bodymovin和Lottie:把AE动画转换成HTML5/Android/iOS原生动画
前段时间听部门老大说,Airbnb出了个移动端的动画库Lottie,可以和一个名叫Bodymovin的AE插件结合起来,把在AE上做好的动画导出为json文件,然后以Android/iOS原生动画的形 ...
- [iOS]过渡动画之高级模仿 airbnb
注意:我为过渡动画写了两篇文章:第一篇:[iOS]过渡动画之简单模仿系统,主要分析系统简单的动画实现原理,以及讲解坐标系.绝对坐标系.相对坐标系,坐标系转换等知识,为第二篇储备理论基础.最后实现 Ma ...
随机推荐
- 启动Apache出现问题:一直停留在启动界面
问题描述: 由于需要php_curl模块,因此直接在php.ini文件将前面的分号去掉 ,但是重启Apache时出现:一直停留在启动界面,Apache无法正常启动,查看错误日志,显示如下: 解决方 ...
- 收集—— css实现垂直居中
Method1: 在父元素上设置display:table-cell;vertical-align:middle(父元素不能设置浮动) Method2: 使用flex:父元素设置成display: f ...
- Mac上编译并运行Android5.0源码
下载.配置环境.build和运行参考的都是Android Source提供的文档,包括:Initializing a Build Environment,Downloading the Source和 ...
- Kotlin编码----var和val的区别
var是一个可变变量,这是一个可以通过重新分配来更改为另一个值的变量.这种声明变量的方式和Java中常规的变量的声明方式一样. val是一个只读变量,这种声明变量的方式相当于java中的final变量 ...
- [转载] 深入剖析 redis 主从复制
转载自http://www.cnblogs.com/daoluanxiaozi/p/3724299.html 主从概述 redis 支持 master-slave(主从)模式,redis server ...
- 自动化部署必备技能—部署yum仓库、定制rpm包
部署yum仓库.定制rpm包 目录 第1章 扩展 - yum缓存 1.1 yum缓存使用步骤... 1 1.1.1 导言... 1 1.1.2 修改配置文件... 1 1.1.3 使用缓存... 1 ...
- AbpZero双重认证之短信的坑
一.什么是双重认证 所谓双重认证简单来说就是除了用户名密码方式外,还额外增加了一道登录屏障.登录时先输入用户名和密码,正确后会向邮箱或手机号发送一个验证码(取决于您采用何种方式,甚至可以采用银行的电子 ...
- Foundation基础框架
自己总结的 // // main.m // 01-结构体 // // Created by Mac-ZhangXiaoMeng on 14/12/29. // Copyright (c) 2014年 ...
- 【微软大法好】VS Tools for AI全攻略(3)
接着上文,现在我们需要一种穷人的方法来搭建好Azure虚拟机. 思路很简单,因为AI组件的原理其实是传送了script文件和命令上去,那么我们这个虚拟机只要做好了所有的配置,那么我们就可以将它当作深度 ...
- jquery无new构建学习笔记
当我们想要创建一个对象,我们可能使用new方法去构建一个对象,那按道理jquery也是一个对象,应该也是用new jquery()来构建呀为什么我们创建jquery对象不用new jquery()而是 ...