QQ粘性効果
7435 ワード
## BageView.m
@interface BageView ()
//
@property (nonatomic, weak) CAShapeLayer *shapeLayer;
//
@property (nonatomic, weak) UIView *smallCircleView;
@end
@implementation BageView
//
- (CAShapeLayer *)shapeLayer
{
if (_shapeLayer == nil) {
//
CAShapeLayer *layer = [CAShapeLayer layer];
layer.fillColor = [UIColor redColor].CGColor;
[self.superview.layer insertSublayer:layer atIndex:0];// ?
_shapeLayer = layer;
}
return _shapeLayer;
}
//
- (instancetype)initWithFrame:(CGRect)frame
{
if (self = [super initWithFrame:frame]) {
[self setUp];
}
return self;
}
//
- (void)awakeFromNib
{
//
[self setUp];
}
//
- (void)setUp
{
## view ( storyboard , )
// :
self.backgroundColor = [UIColor redColor];
//
self.layer.cornerRadius = self.bounds.size.width * 0.5;
//
self.titleLabel.font = [UIFont systemFontOfSize:12];
//
[self setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
##
// pan
UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(pan:)];
[self addGestureRecognizer:pan];
## view
//
UIView *smallCircleView = [[UIView alloc] init];
//
smallCircleView.frame = self.frame;
//
smallCircleView.backgroundColor = self.backgroundColor;
//
smallCircleView.layer.cornerRadius = self.layer.cornerRadius;
//
[self.superview insertSubview:smallCircleView belowSubview:self];
_smallCircleView = smallCircleView;
}
##
- (void)pan:(UIPanGestureRecognizer *)pan
{
//
CGPoint transP = [pan translationInView:self];
// ,
// transform center
// self.transform = CGAffineTransformTranslate(self.transform, transP.x, transP.y);
CGPoint center = self.center;
center.x += transP.x;
center.y += transP.y;
self.center = center;
//
[pan setTranslation:CGPointZero inView:self];
## ( )
//
CGFloat distance = [self distanceWithSmallView:_smallCircleView bigView:self];
## ,
// ,
CGFloat smallR = self.bounds.size.width * 0.5 - distance / 10.0;
_smallCircleView.bounds = CGRectMake(0, 0, smallR * 2 , smallR * 2);
//
_smallCircleView.layer.cornerRadius = smallR;
, , ( , 0, return)
//
UIBezierPath *path = [self pathWithSmallView:_smallCircleView bigView:self];
if (self.smallCircleView.hidden == NO) { // ,
//
self.shapeLayer.path = path.CGPath;
}
## , ( )
// 60 ,
if (distance > 60) {
//
_smallCircleView.hidden = YES;
//
// self.shapeLayer.hidden = YES;
[self.shapeLayer removeFromSuperlayer];
}
## , imageView ,
if (pan.state == UIGestureRecognizerStateEnded) { // ,
if (distance > 60) {
NSMutableArray *images = [NSMutableArray array];
// gif
for (int i = 1; i <= 8; i++) {
NSString *imageName = [NSString stringWithFormat:@"%d",i];
UIImage *image = [UIImage imageNamed:imageName];
[images addObject:image];
}
// gif
UIImageView *imageView = [[UIImageView alloc] initWithFrame:self.bounds];
//
imageView.animationImages = images;
imageView.animationDuration = 1;
[self addSubview:imageView];
//
[imageView startAnimating];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.9 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[self removeFromSuperview];
});
## , ,
}else{ //
//
[UIView animateWithDuration:0.25 delay:0 usingSpringWithDamping:0.1 initialSpringVelocity:0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
self.center = self.smallCircleView.center;
} completion:^(BOOL finished) {
//
self.smallCircleView.hidden = NO;
}];
}
}
}
, , ( , 0, return))
//
- (UIBezierPath *)pathWithSmallView:(UIView *)smallView bigView:(UIView *)bigView
{
//
CGFloat d = [self distanceWithSmallView:smallView bigView:bigView];
CGFloat y1 = smallView.center.y;
CGFloat x1 = smallView.center.x;
CGFloat r1 = smallView.layer.cornerRadius;
CGFloat y2 = bigView.center.y;
CGFloat x2 = bigView.center.x;
CGFloat r2 = bigView.layer.cornerRadius;
// 0,
if (d == 0) return nil;
// cosθ
CGFloat cosθ = (y2 - y1) / d;
// sinθ
CGFloat sinθ = (x2 - x1) / d;
// A:
CGPoint pointA = CGPointMake(x1 - r1 * cosθ, y1 + r1 * sinθ);
// B:
CGPoint pointB = CGPointMake(x1 + r1 * cosθ, y1 - r1 * sinθ);
// C:
CGPoint pointC = CGPointMake(x2 + r2 * cosθ, y2 - r2 * sinθ);
// D:
CGPoint pointD = CGPointMake(x2 - r2 * cosθ, y2 + r2 * sinθ);
// O:
CGPoint pointO = CGPointMake(pointA.x + d * 0.5 * sinθ, pointA.y + d * 0.5 * cosθ);
// P:
CGPoint pointP = CGPointMake(pointB.x + d * 0.5 * sinθ, pointB.y + d * 0.5 * cosθ);
//
UIBezierPath *path = [UIBezierPath bezierPath];
// nan == null
[path moveToPoint:pointA];
// AB
[path addLineToPoint:pointB];
// BC
//
[path addQuadCurveToPoint:pointC controlPoint:pointP];
// CD
[path addLineToPoint:pointD];
// DA
[path addQuadCurveToPoint:pointA controlPoint:pointO];
return path;
}
## ( )
//
- (CGFloat)distanceWithSmallView:(UIView *)smallView bigView:(UIView *)bigView
{
CGFloat offsetX = bigView.center.x - smallView.center.x;
CGFloat offsetY = bigView.center.y - smallView.center.y;
return sqrt(offsetX * offsetX + offsetY * offsetY);
}
- (void)setHighlighted:(BOOL)highlighted{}
@end
##VC.m , autoMask ,
- (void)viewDidLoad {
[super viewDidLoad];
// autoMask
self.view.translatesAutoresizingMaskIntoConstraints = NO;
}