QQ粘性効果

7435 ワード

  • 効果:情報提示数のボタンをドラッグすると、ボタンを伸ばしているような感じがします.一定の範囲にドラッグすると、ボタン(小さな円が抽出されます)が開き、手の小さな円を離すと爆発します.小さな円を抽出した後、小さな円を前の位置に戻すと、小さな円は
  • に戻ります.
  • コア計算式:(図中のA、B、C、D、O、P点式を参照)
  • ステップ:
  • 大きな円viewを生成し、プロパティを設定する(例はstoryboardで作成されるため、次のコードにはこのステップがない)
  • ジェスチャードラッグ設定ボタンに従って
  • 移動する.
  • ボタンの元の位置にボタンとそっくりの小さな円view
  • を生成する.
  • パッケージ両円中心距離計算方法(勾配定理)
  • 両円の中心距離及び一定の割合に応じる、小円の大きさ変形
  • を設ける.
  • コア計算式を利用して、直線と曲線の経路を計算して描画し、形状レイヤーを通じて不規則な矩形を生成する(計算方法パッケージ、2円の中心距離が0であることに注意して、直接return)
  • 両円の中心距離が一定距離に達した後、引き抜き効果(小円同時隠蔽)
  • を実現する.
  • 手を離す位置が爆発範囲外の場合は、コアアニメーションまたはimageViewを介して手を離して爆発フレームアニメーションを再生し、親コントロールから
  • 円を除去します.
  • 手を離す位置が爆発範囲内にある場合、スプリング効果により大円を原点に戻し、小円
  • を表示する.
  • VC.mでautoMaskを自動レイアウトに変換しないと、シフトに問題が発生します[画像のアップロードに失敗しました...(image-2120148-15145997537)]
  • ## 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;
    }