• QQ中未读气泡拖拽消失的实现(参照一位年轻牛B的博主的思路自己实现了一下)


    原文链接:http://kittenyang.com/drawablebubble/,博主年轻却很有思想。相仿的年纪,很佩服他!

    首先分析拖拽时的图,大圆、不规则的图(实际上时有规律的不然也画不出来,这里只是代指)、小圆。对,拖拽时的效果就是这三部分拼凑成的。博主 大圆用了UIView 不规则的图 用CAShapeLayer ,小圆也是UIView,在我自己实现时,发现其实大圆用UIView,小圆和中间那部分 用CAShapeLayer就能画出来了。CAHShapeLayer 都知道给它传一个path,它就能根据path生成任意形状的layer。所以后面其实就是用贝塞尔曲线构建这个path,这个path构建对于我这种被大学上了四年的人来说,没有前人的基础,估计打死也没有这种想法。

    下面就是 构建 A、B、C、D、O、P 这六个点,创建path,给CAShapeLayer,生成layer。

    下面时部分代码:

    处理手势的

    /** 处理手势 */
    - (void)panGesture:(UIPanGestureRecognizer *)gesture {
        // self.containerView bubbleView 的父视图
        CGPoint newCenter = [gesture locationInView:self.containerView];
        
        self.bubbleView.center = newCenter;
        
        if (gesture.state == UIGestureRecognizerStateBegan) {
            
            // 手势开始 移除动画
            [self.bubbleView.layer removeAllAnimations];
            
        }else if (gesture.state == UIGestureRecognizerStateChanged) {
            
            // 圆心距离 >= 断裂的距离
            if (centerDistance >= self.maxDistance ) {
                
                // 大于设定的值时 断裂 移除shapeView
                [self.shapeLayer removeFromSuperlayer];
                
            }else {
                
                // 更新 贝塞尔曲线shapeView 的形状
                [self updateCoordinate:newCenter];
            }
            
        }else if (gesture.state == UIGestureRecognizerStateCancelled || gesture.state == UIGestureRecognizerStateEnded || gesture.state == UIGestureRecognizerStateFailed) {
            
            // 大于 设定值 并且实现了 block,执行block
            if (centerDistance >= self.maxDistance && self.breakComplete) {
                self.breakComplete();
            }else {
                
                // 让小球回到 初始点
                [UIView animateWithDuration:0.5 delay:0 usingSpringWithDamping:0.4 initialSpringVelocity:0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
                    self.bubbleView.center = initBubbleCenter;
                } completion:^(BOOL finished) {
                    // 小球回到初始点 圆心距离归零
                    centerDistance = 0;
                    
                    if (finished && self.achieveAnimation) {
                        [self animationForBubbleView];
                    }
                    
                }];
    
            }
            
            [self.shapeLayer removeFromSuperlayer];
            
        }
    }

        手势的拖拽导致大圆中心点更新,以此更新A、B、C、D、O、P六个点,跟新path,对于CAShapeLayer来说,你传给他一个新的path,它就会更新它的形状

    /** 根据新的中心点 更新 ABCDOP6个点 以更行CAShapeLayer 的path */
    - (void)updateCoordinate:(CGPoint)currentCenter {
        
        CGFloat x2 = currentCenter.x;
        CGFloat y2 = currentCenter.y;
        CGFloat x1 = initBubbleCenter.x;
        CGFloat y1 = initBubbleCenter.y;
        
        // 当前圆心 于 初始点圆心距离
        centerDistance = sqrt((x2-x1) * (x2-x1)+(y2-y1)*(y2-y1));
        
        
        // 更新初始化圆心处 圆的半径(随着拖拽的距离的增大而减小,达到设定的距离 消失)
        
        
        if (centerDistance == 0) {
            cos = 1;
            sin = 0;
        }else{
            cos = (y2-y1) / centerDistance;
            sin = (x2-x1) / centerDistance;
        }
        r1 = r2 * (1 - (centerDistance / self.maxDistance) * self.modulus);
        
        A = CGPointMake(x1 - r1*cos, y1 + r1*sin);
        B = CGPointMake(x1 + r1*cos, y1 - r1*sin);
        C = CGPointMake(x2 + r2*cos, y2 - r2*sin);
        D = CGPointMake(x2 - r2*cos, y2 + r2*sin);
        
        O = CGPointMake(A.x + centerDistance / 2.0*sin, A.y + centerDistance / 2.0 * cos);
        P = CGPointMake(B.x + centerDistance / 2.0*sin, B.y + centerDistance / 2.0*cos);
        UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:initBubbleCenter radius:r1 startAngle:0 endAngle:M_PI * 2 clockwise:1];
        
        UIBezierPath *path1 = [UIBezierPath bezierPath];
        [path1 moveToPoint:A];
        [path1 addLineToPoint:B];
        [path1 addQuadCurveToPoint:C controlPoint:P];
        [path1 addLineToPoint:D];
        [path1 addQuadCurveToPoint:A controlPoint:O];
        [path appendPath:path1];
        
        self.shapeLayer.path = path.CGPath;
        
        
    }

    完整代码:http://pan.baidu.com/s/1dEzZLst

  • 相关阅读:
    那些年做过的外包 之 健康小屋
    Raize 重新编译
    解码淘口令?
    单品优惠券炸了
    如何共享联盟cookie
    阿里妈妈账号登录状态如何长时间保存
    delphi 图像旋转
    Canvas: Out of system resources
    关于&$地址传递的练习
    解决XAMPP中,MYSQL因修改my.ini后,无法启动的问题
  • 原文地址:https://www.cnblogs.com/CyanStone/p/5111178.html
Copyright © 2020-2023  润新知