p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 17.0px “Helvetica Neue”; color: #e7e8eb; background-color: #292b36 }
p.p2 { margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica; background-color: #292b36; min-height: 14.0px }
p.p3 { margin: 0.0px 0.0px 0.0px 0.0px; font: 17.0px “Helvetica Neue”; color: #6544e9; background-color: #292b36 }
p.p4 { margin: 0.0px 0.0px 0.0px 0.0px; font: 15.0px Menlo; color: #18b5b1; background-color: #292b36 }
p.p5 { margin: 0.0px 0.0px 0.0px 0.0px; font: 17.0px “Helvetica Neue”; color: #68878f; background-color: #292b36 }
span.s1 { color: #68878f }
span.s2 { color: #6544e9 }
span.s3 { font: 15.0px Menlo; color: #18b5b1 }
span.s4 { color: #e7e8eb }

>需求分析:这种功能常见于数值实时加减,比如对音量的控制。手指滑动圆盘,数值随着滑动的角度而改变,效果图跟最终实现GIF如下。([DCAutoImaginaryLayer](https://github.com/XDChang/DCAutoImaginaryLayer)

 

>功能分析:自定义圆环音量调节显示,跟随手指旋转角度加减音量,利用了核心动画,图层,贝赛尔函数,三角函数与反三角函数;对外围螺纹线裁剪,使用了image layer mask 根据图片layer进行裁剪。一开始我想自己画螺纹线来着,无奈知识面太狭隘了,找了很多资料还是不会,所以最后就找了张有螺纹线的图片进行裁剪代替了。

 

>实现原理:1.`CAShapeLayer`有虚线`lineDashPattern`的设置,可以实现这种间隔layer,不要自己费劲脑汁的一个个画了;2.利用图片裁剪螺纹线,也不用费劲脑汁的去想怎么画这个了;3.实现系统方法`touchesMoved:`处理角度,实时改变`UIBezierPath`并更新图层,实现最终效果。

 

![DCAutoImaginaryLayer.png](//upload-images.jianshu.io/upload_images/1992794-e62743302ebde7ec.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

 

 

![transformView.gif](https://upload-images.jianshu.io/upload_images/1992794-d5c8c4be1c38aab2.gif?imageMogr2/auto-orient/strip)

 

 

 

###核心代码

####1.根据图片layer进行裁剪:

“`

CALayer *maskLayer = [CALayer layer];

maskLayer.frame = CGRectMake(frame.size.width/2 – 97, frame.size.height/2 – 97, 194, 194);

UIImage *maskImage = [UIImage imageNamed:@”volume_area”];

maskLayer.contents = (__bridge id)maskImage.CGImage;

self.layer.mask = maskLayer;

“`

####2.虚线的设置:

“`

//每个虚线宽度为2,间隔为3 整个线条宽度为30

_shapeLayer.lineWidth = 30.0f;

_shapeLayer.lineDashPattern = [NSArray arrayWithObjects:[NSNumber numberWithInt:4], [NSNumber numberWithInt:3], nil];

“`

####3.path角度的处理:

“`

– (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{

UITouch *touch = [touches anyObject];

CGPoint touchPoint = [touch locationInView:self];

_endPoint = touchPoint;

 

float x = _endPoint.y – self.frame.size.height/2;

float y = _endPoint.x – self.frame.size.width/2;

float a = atanf(x/y);

float angle = 0.0;

// ========== 4个象限角度的处理 start =============//

if (x <0 && y < 0) {

angle = a-M_PI;

}

if (x > 0 && y < 0) {

angle = M_PI + a;

}

if (x > 0 && y > 0) {

angle =  a;

}

if (x < 0 && y > 0) {

angle = a;

}

// ========== 4个象限角度的处理 end =============//

_path = [UIBezierPath bezierPathWithArcCenter:CGPointMake(self.frame.size.width/2, self.frame.size.height/2) radius:90 startAngle:-M_PI endAngle:angle clockwise:1];

_shapeLayer.path = _path.CGPath;

}

“`

###思路分析

>要想layer跟着手指滑动实时更新,其实比较难想到的就是角度的处理,怎么实时获取正确的角度也是一个关键点。我首先想到的就是利用反三角函数获取角度,但是不能仅仅这样,还要注意四个象限x 跟 y 值的不同导致角度获取的不连续,需要手动处理。

****

这些小功能虽然不是很难,但是我能通过独立思考并利用自己所了解的知识点去实现它,我觉得很有成就感,它也是我进步的一个记录。

****

*转载请注明出处* © XDChang

[DCAutoImaginaryLayer](https://github.com/XDChang/DCAutoImaginaryLayer)

 

版权声明:本文为XuDechang原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/XuDechang/p/9287739.html