iOS之贝塞尔曲线

727 阅读2分钟

官方文档developer.apple.com/documentati…

原创不易,对你有帮助的话,点个赞支持一下~

聊天冒泡 的界面

一、Objective-C版本(如需要Swift版本,还请留言,后续更新)

效果图如下:

图描述:红色的是点,从图可知,四个角分别都有三个点,这里要做圆角处理,我暂时想到的是用 addArcWithCenter 方法来画弧线,里面的角其实是一个圆点。对于圆的角度如下图(这个圆形图借用了其它博主的):

代码实现如下:

- (void)drawBubble:(CGRect)rect {
    
    UIBezierPath *mainPath = [[UIBezierPath alloc] init];
    
    CGFloat maxX = rect.size.width - 50;
    CGFloat maxY = rect.size.height;
    CGFloat minX = 0;
    CGFloat minY = 0;
    
    //自定义圆角的半径
    CGFloat radius = 10;
    
    /**
     顶点值点越小越往里面的收缩
     **/
    //冒泡三角形突出的顶点
    CGFloat cornerLength = 30;
    
    /**
     top点和bottom点越小越往中间的收缩
     **/
    //冒泡三角形的底边的top点
    CGFloat cornerTopY1 = 15;
    //冒泡三角形的底边的bottom点
    CGFloat cornerBottomY2 = 15;
    
    //起点
    [mainPath moveToPoint:CGPointMake(maxX - radius, maxY)];
    
    [mainPath addLineToPoint:CGPointMake(minX + radius, maxY)];
    [mainPath addArcWithCenter:CGPointMake(minX + radius, maxY - radius) radius:radius startAngle:0.5*M_PI endAngle:1*M_PI clockwise: true];
    [mainPath addLineToPoint:CGPointMake(minX, maxY - radius)];
    
    
    [mainPath addLineToPoint:CGPointMake(minX, radius)];
    [mainPath addArcWithCenter:CGPointMake(radius, radius) radius:radius startAngle:1*M_PI endAngle:1.5*M_PI clockwise: true];
    [mainPath addLineToPoint:CGPointMake(radius, minY)];
    
    [mainPath addLineToPoint:CGPointMake(maxX - radius, minY)];
    [mainPath addArcWithCenter:CGPointMake(maxX - radius, minY + radius) radius:radius startAngle:1.5*M_PI endAngle:0*M_PI clockwise: true];
    [mainPath addLineToPoint:CGPointMake(maxX, minY + 10)];
    
    
    [mainPath addLineToPoint:CGPointMake(maxX, maxY/2 - cornerTopY1)];
    [mainPath addLineToPoint:CGPointMake(maxX + cornerLength, maxY/2)];
    [mainPath addLineToPoint:CGPointMake(maxX, maxY/2 + cornerTopY1)];
    
    [mainPath addLineToPoint:CGPointMake(maxX, maxY - radius)];
    [mainPath addArcWithCenter:CGPointMake(maxX - radius, maxY - radius) radius:radius startAngle:0*M_PI endAngle:0.5*M_PI clockwise: true];
    
    [mainPath closePath];
    [mainPath stroke];
    
    CAShapeLayer *shapeLayer = [[CAShapeLayer alloc] init];
    shapeLayer.path = mainPath.CGPath;
    
    self.layer.mask = shapeLayer;
}

**备注:**我这里是的聊天冒泡界面是整个UIView来的,因此可以在里面添加内容等。这里需要在Draw方法里面的进行调用(Draw方法是指UIView类里面方法,非自定义)

实现圆圈动画

效果静态图如下:

    private var gradientLayer: CALayer?    // MARK:  加载小圆圈
    func addLoadingAnimation(superView: UIView) {
        if self.gradientLayer != nil {
            self.gradientLayer?.removeFromSuperlayer()
            self.gradientLayer = nil
        }
        
        // 形状
        let lineWidth: CGFloat = 7
        let middleColor = UIColor.hex_00efe7
        let circleLayer = CAShapeLayer.init()
        circleLayer.lineWidth = lineWidth;
        //        circleLayer.frame = self.translateTypeView.bounds
        circleLayer.fillColor = UIColor.clear.cgColor
        circleLayer.strokeColor = UIColor.black.cgColor
        
        // 曲线
        //        let circlePath = UIBezierPath.init(arcCenter: CGPoint(x: self.translateTypeView.width / 2, y: self.translateTypeView.height / 2), radius: self.translateTypeView.height / 2, startAngle: CGFloat(-Double.pi / 2), endAngle: CGFloat(Double.pi * 2), clockwise: true) // 有毛边
        let circlePath = UIBezierPath.init(ovalIn: superView.bounds)
        circleLayer.path = circlePath.cgPath
        
        // 渐变
        self.gradientLayer = CALayer.init()
        // 渐变1
        let gradient = CAGradientLayer.init()
        gradient.frame = CGRect(x: -lineWidth * 2, y: -lineWidth * 2, width: superView.bounds.size.width / 2 + lineWidth * 2, height: superView.bounds.size.height + lineWidth*3)
        gradient.colors = [UIColor.hex_333333.cgColor, middleColor.cgColor]
        //        gradient.locations = [NSNumber(value: 0.1), NSNumber(value:1.0)] // 设置比例
        gradient.startPoint = CGPoint(x: 0.0, y: 0.0)
        gradient.endPoint = CGPoint(x: 0.0, y: 1.0)
        gradient.shadowPath = circlePath.cgPath
        
        // 渐变1
        let gradient2 = CAGradientLayer.init()
        gradient2.frame = CGRect(x: superView.bounds.size.width / 2, y: -lineWidth * 2, width: superView.bounds.size.width / 2 + lineWidth * 2, height: superView.bounds.size.height + lineWidth*3)
        gradient2.colors = [UIColor.hex_00efe7.cgColor, middleColor.cgColor]
        //        gradient2.locations = [NSNumber(value: 0.1), NSNumber(value:1.0)]
        gradient2.startPoint = CGPoint(x: 0.0, y: 0.0)
        gradient2.endPoint = CGPoint(x: 0.0, y: 1.0)
        gradient2.shadowPath = circlePath.cgPath
        
        gradientLayer!.addSublayer(gradient)
        gradientLayer!.addSublayer(gradient2)
        gradientLayer!.mask = circleLayer
        
        // CABasicAnimation strokeEnd动画
//        let pathAnimation = CABasicAnimation()
//        pathAnimation.keyPath = "strokeEnd"
//        pathAnimation.duration = 1.0
//        pathAnimation.fillMode = CAMediaTimingFillMode.forwards
//        pathAnimation.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.linear)
//        pathAnimation.fromValue = 0.0
//        pathAnimation.toValue = 1.0
//        pathAnimation.repeatCount = 1
//        circleLayer.add(pathAnimation, forKey: "strokeEndAnimationcircle")
        
        // 旋转z
        let rotateAnima = CABasicAnimation.init(keyPath: "transform.rotation.z")
        rotateAnima.duration = 1.0
        rotateAnima.repeatCount = HUGE
        rotateAnima.fromValue = NSNumber(value: 0.0)
        rotateAnima.toValue = NSNumber(value: Double.pi * 2)
//        rotateAnima.beginTime = CACurrentMediaTime() + 3.0 / 4.0
        
        gradientLayer!.add(rotateAnima, forKey: "rotateAnimationcircle")
        gradientLayer!.frame = superView.bounds  // 一定要设置frame,不然anchorPoint(锚点--旋转中心点始终是(0,0))
        superView.layer.addSublayer(gradientLayer!)
    }