展示效果
实现思路
- 2个圆(一个是固定圆,一个是可拖动的圆)
- 贝塞尔画形状
- 拖动的时候固定圆的比例是缩小的
- 到一定距离的时候会断开
- 松开手势就会回弹到原地
事前准备工作
@property (nonatomic, strong) UIView *view1;
@property (nonatomic, strong) UIView *view2;
@property (nonatomic, strong) CAShapeLayer *shapeLayer;
@property (nonatomic, assign) CGPoint oldViewCenter;
@property (nonatomic, assign) CGRect oldViewFram;
@property (nonatomic, assign) CGFloat r1;
- (void)setup{
UIView *view1 = [[UIView alloc] initWithFrame:CGRectMake(CGRectGetWidth(self.view.bounds) / 2, CGRectGetHeight(self.view.bounds) * 1/9, 40, 40)];
view1.backgroundColor = [UIColor redColor];
view1.layer.cornerRadius = 20;
_view1 = view1;
[self.view addSubview:view1];
UIView *view2 = [[UIView alloc] initWithFrame:_view1.frame];
view2.backgroundColor = [UIColor redColor];
view2.layer.cornerRadius = 20;
_view2 = view2;
[self.view addSubview:view2];
//添加label
UILabel *numL = [[UILabel alloc] initWithFrame:_view2.bounds];
numL.text = @"66";
numL.textAlignment = NSTextAlignmentCenter;
numL.textColor = [UIColor whiteColor];
[_view2 addSubview:numL];
//添加手势
UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panAction:)];
[_view2 addGestureRecognizer:pan];
//实例化CAShapeLayer
_shapeLayer = [CAShapeLayer layer];
_shapeLayer.fillColor = [UIColor redColor].CGColor;
// [self.view.layer addSublayer:_shapeLayer];
_oldViewFram = _view1.frame;
_oldViewCenter = _view1.center;
_r1 = CGRectGetWidth(_view1.frame)/2;
}
- 需要保存原先中心点的位置
- 需要保存原先圆的大小,因为在断开的时候需要回到原来的样子
- shapeLayer 是直接初始化添加,在拖拽中改变path就可以了
- (void)panAction:(UIPanGestureRecognizer *)ges{
if (ges.state == UIGestureRecognizerStateChanged) {
//view2跟着移动
_view2.center = [ges locationInView:self.view];
//
if (_r1 < wift
_view1.hidden = YES;
[_shapeLayer removeFromSuperlayer];
}else{
//计算出6个关键点,然后画贝塞尔曲线
[self caculPoint];
}
}else if (ges.state == UIGestureRecognizerStateFailed || ges.state == UIGestureRecognizerStateEnded || ges.state == UIGestureRecognizerStateCancelled){
[_shapeLayer removeFromSuperlayer];
[UIView animateWithDuration:.5 delay:0 usingSpringWithDamping:.3 initialSpringVelocity:0 options:UIViewAnimationOptionCurveEaseOut animations:^{
_view2.center = _oldViewCenter;
} completion:^(BOOL finished) {
_view1.hidden = NO;
_r1 = _oldViewFram.size.width/2;
_view1.frame = _oldViewFram;
_view1.layer.cornerRadius = _r1;
}];
}
}
- 因为在结束动画之后会需要很多点的复原问题,所以我们在开始的时候就需要记录
- [_shapeLayer removeFromSuperlayer]; 在取消和结束的时候还是需要移除layer的
不然会出现画的红色背景还在的情况
- usingSpringWithDamping 弹簧阻力效果
- (void)caculPoint{
//1.求出2个中心点
CGPoint center1 = _view1.center;
CGPoint center2 = _view2.center;
//2.计算2个中心点的距离
CGFloat dis = sqrtf((center1.x - center2.x)*(center1.x - center2.x) + (center1.y - center2.y)*(center1.y - center2.y));
//3.计算正弦余弦
CGFloat sin = (center2.x - center1.x) / dis;
CGFloat cos = (center1.y - center2.y) / dis;
//4.计算半径
CGFloat r1 = CGRectGetWidth(_oldViewFram)/2 - dis/20;
CGFloat r2 = CGRectGetWidth(_view2.bounds)/2;
_r1 = r1;
NSLog(@"%f",r1);
//5.计算6个关键点
CGPoint pA = CGPointMake(center1.x - cos*r1, center1.y - sin*r1);
CGPoint pB = CGPointMake(center1.x + cos*r1, center1.y + sin*r1);
CGPoint pD = CGPointMake(center2.x - cos*r2, center2.y - sin*r2);
CGPoint pC = CGPointMake(center2.x + cos*r2, center2.y + sin*r2);
CGPoint pP = CGPointMake(pB.x + dis/2*sin, pB.y - dis/2*cos);
CGPoint pO = CGPointMake(pA.x + dis/2*sin, pA.y - dis/2*cos);
//6.画贝塞尔曲线
UIBezierPath *path = [UIBezierPath bezierPath];
[path moveToPoint:pA];
[path addQuadCurveToPoint:pD controlPoint:pO];
[path addLineToPoint:pC];
[path addQuadCurveToPoint:pB controlPoint:pP];
[path closePath];
//7.修改_shapeLayer的path
_shapeLayer.path = path.CGPath;
[self.view.layer insertSublayer:_shapeLayer below:_view2.layer];
//8.重新设置view的大小
_view1.center = _oldViewCenter;
_view1.bounds = CGRectMake(0, 0, _r1*2, _r1*2);
_view1.layer.cornerRadius = _r1;
}
- CGRectGetWidth(_oldViewFram)/2 - dis/20; 这里再次设置宽度的时候需要用到原先的那个值,不然r1的值就会有问题