自定義圓環,跟隨手指旋轉角度加減layer

XDChang發表於2018-07-10

需求分析:這種功能常見於數值實時加減,比如對音量的控制。手指滑動圓盤,數值隨著滑動的角度而改變,效果圖跟最終實現GIF如下。(DCAutoImaginaryLayer

功能分析:自定義圓環音量調節顯示,跟隨手指旋轉角度加減音量,利用了核心動畫,圖層,貝賽爾函式,三角函式與反三角函式;對外圍螺紋線裁剪,使用了image layer mask 根據圖片layer進行裁剪。一開始我想自己畫螺紋線來著,無奈知識面太狹隘了,找了很多資料還是不會,所以最後就找了張有螺紋線的圖片進行裁剪代替了。

實現原理:1.CAShapeLayer有虛線lineDashPattern的設定,可以實現這種間隔layer,不要自己費勁腦汁的一個個畫了;2.利用圖片裁剪螺紋線,也不用費勁腦汁的去想怎麼畫這個了;3.實現系統方法touchesMoved:處理角度,實時改變UIBezierPath並更新圖層,實現最終效果。

DCAutoImaginaryLayer.png

transformView.gif

核心程式碼

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

相關文章