"凸"圆角,"凹"圆角

2021-02-08  本文已影响0人  山已几孑

如图,也不知道这圆角叫啥,也没搜到,只能拼了一个出来,功能简单,也没啥Demo

image.png

。直接贴一个playground.swift, 如果有更好地的办法,也希望能指点下,总觉得还有规律没有找到。

//: A UIKit based Playground for presenting user interface
  
import UIKit
import PlaygroundSupport
import MachO
class CornerRectView : UIView {
    
    class Corner: Equatable {
        static func == (lhs: CornerRectView.Corner, rhs: CornerRectView.Corner) -> Bool {
            return lhs.origin.rawValue == rhs.origin.rawValue
        }
        
        struct CornerOrigin: OptionSet {
            let rawValue: Int

            static let bottomRight = CornerOrigin(rawValue: 1)
            static let bottomLeft = CornerOrigin(rawValue: 2)
            static let topLeft = CornerOrigin(rawValue: 4)
            static let topRight = CornerOrigin(rawValue: 8)
        }
        var origin: CornerOrigin
        var cornerRadius: CGFloat = 0
        
        init(origin: CornerOrigin, cornerRadius: CGFloat) {
            self.origin = origin
            self.cornerRadius = cornerRadius
        }
    }
    override var backgroundColor: UIColor? {
        set {
            ky_backgroundColor = newValue
            self.setNeedsDisplay()
        }
        get {
            return ky_backgroundColor
        }
    }
    
    private var ky_backgroundColor: UIColor?
    
    let corners: [Corner] = [
        Corner(origin: .bottomRight, cornerRadius: 0),
        Corner(origin: .bottomLeft, cornerRadius: 0),
        Corner(origin: .topLeft, cornerRadius: 0),
        Corner(origin: .topRight, cornerRadius: 0)
    ]
    var roundCornerLayer: CALayer?

/// 只提供俩种修改方式,一个是统一修改,传Corner.CornerOrigin就行,
    func drawRoundCorner(cornerOrigin: Corner.CornerOrigin, cornerRadius: CGFloat) {
        for corner in corners {
            if corner.origin .isSubset(of: cornerOrigin) {
                corner.cornerRadius = cornerRadius
            }
        }
        self.setNeedsDisplay()
    }
/// 只提供俩种修改方式,一个是分别修改,传Corner的数组Corner(origin: .topRight, cornerRadius: 0)
    func drawCornerWith(sets:[Corner]) -> Void {
  //遍历修改,如果重复就重复修改,务必保证正确
        for newCorner in sets {
            if let oldCorner = corners.first(where: {newCorner == $0}) {
                oldCorner.cornerRadius = newCorner.cornerRadius;
            }
        }
        self.setNeedsDisplay()
    }

    override func draw(_ rect: CGRect) {
        super.draw(rect)

        let path2 = UIBezierPath()
        // 排一下序,保证按照一定的顺序画角
        let sortedCorner = corners.sorted(by: {$0.origin.rawValue < $1.origin.rawValue})
        
        for corner in sortedCorner {
            let cornerRadius = corner.cornerRadius
            var center: CGPoint
            switch corner.origin {
            case .bottomRight:
                center = CGPoint(x: bounds.maxX - abs(cornerRadius), y: bounds.maxY - abs(cornerRadius))
                if path2.isEmpty {
                    path2.move(to: CGPoint(x: bounds.maxX , y: bounds.maxY - abs(cornerRadius)))
                } else {
                    path2.addLine(to: CGPoint(x: bounds.maxX , y: bounds.maxY - abs(cornerRadius)))
                }
                if cornerRadius < 0 {
                    center = center.applying(CGAffineTransform(translationX: -corner.cornerRadius, y: -corner.cornerRadius))
                }
            case .bottomLeft:
                center = CGPoint(x: bounds.minX + abs(cornerRadius), y: bounds.maxY - abs(cornerRadius))
                if path2.isEmpty {
                    path2.move(to: CGPoint(x: bounds.minX + abs(cornerRadius), y: bounds.maxY))
                } else {
                    path2.addLine(to: CGPoint(x: bounds.minX + abs(cornerRadius), y: bounds.maxY))
                }
                if cornerRadius < 0 {
                    center = center.applying(CGAffineTransform(translationX: corner.cornerRadius, y: -corner.cornerRadius))
                }
            case .topLeft:
                center = CGPoint(x: bounds.minX + abs(cornerRadius), y: bounds.minY + abs(cornerRadius))
                if path2.isEmpty {
                    path2.move(to: CGPoint(x: bounds.minX, y: bounds.minY + abs(cornerRadius)))
                } else {
                    path2.addLine(to: CGPoint(x: bounds.minX, y: bounds.minY + abs(cornerRadius)))
                }
                if cornerRadius < 0 {
                    center = center.applying(CGAffineTransform(translationX: corner.cornerRadius, y: corner.cornerRadius))
                }
            case .topRight:
                center = CGPoint(x: bounds.maxX - abs(cornerRadius), y: bounds.minY + abs(cornerRadius))
                
                if path2.isEmpty {
                    path2.move(to: CGPoint(x: bounds.maxX - abs(cornerRadius), y: bounds.minY))
                } else {
                    path2.addLine(to: CGPoint(x: bounds.maxX - abs(cornerRadius), y: bounds.minY))
                }
                if cornerRadius < 0 {
                    center = center.applying(CGAffineTransform(translationX: -corner.cornerRadius, y: corner.cornerRadius))
                }
            default:
                center = .zero
            }
            let index = log2(CGFloat(corner.origin.rawValue)); // 3
            
            var startAngle = CGFloat.pi * 0.5 * index //CGFloat.pi * 1
            var endAngle = CGFloat.pi * 0.5 * (index + 1)
            
            if cornerRadius < 0 {
                swap(&startAngle, &endAngle)
            }
            path2.addArc(withCenter: center, radius: cornerRadius, startAngle: startAngle, endAngle: endAngle, clockwise: cornerRadius > 0)
        }
        
        path2.close()

        let shapeLayer = CAShapeLayer()
        shapeLayer.path = path2.cgPath
        
        let backgroundLayer = CALayer()
        backgroundLayer.frame = rect
        backgroundLayer.backgroundColor = (ky_backgroundColor ?? UIColor.white).cgColor
        backgroundLayer.mask = shapeLayer

        if self.roundCornerLayer != nil {
            self.roundCornerLayer?.removeFromSuperlayer()
        }
        self.roundCornerLayer = backgroundLayer
        self.layer.insertSublayer(backgroundLayer, at: 0)
    }
}

class MyViewController : UIViewController {
    
    var cornerView: CornerRectView!
    override func loadView() {
        let view = UIView()
        view.backgroundColor = .white
        self.view = view

// 第一个View
        let label = CornerRectView(frame: CGRect(x: 50, y: 40, width: 100, height: 100))
        label.backgroundColor = UIColor.yellow
        label.drawCornerWith(sets: [CornerRectView.Corner(origin: .topLeft, cornerRadius: 20),
                                    CornerRectView.Corner(origin: .topRight, cornerRadius: 20),
                                    CornerRectView.Corner(origin: .bottomRight, cornerRadius: -20),
                                    CornerRectView.Corner(origin: .bottomLeft, cornerRadius: -20)])
        view.addSubview(label)
// 第二个View
        let label11 = CornerRectView(frame: CGRect(x: 250, y: 40, width: 100, height: 100))
        label11.backgroundColor = UIColor.purple
        label11.drawCornerWith(sets: [CornerRectView.Corner(origin: .topLeft, cornerRadius: -20),
                                    CornerRectView.Corner(origin: .topRight, cornerRadius: 0),
                                    CornerRectView.Corner(origin: .bottomRight, cornerRadius: 20),
                                    CornerRectView.Corner(origin: .bottomLeft, cornerRadius: 0)])
        
        view.addSubview(label11)

// 第三个View
        let view2 = CornerRectView(frame: CGRect(x: 50, y: 300, width: 100, height: 100))
        view2.drawRoundCorner(cornerOrigin: [.bottomLeft,.bottomRight, .topLeft, .topRight], cornerRadius: -10)
        view2.backgroundColor = UIColor.blue

        view2.layer.shadowColor = UIColor.black.cgColor
        view2.layer.shadowRadius = 10
        view2.layer.shadowOpacity = 1
        
        view.addSubview(view2)
// 第四个View
        let view21 = CornerRectView(frame: CGRect(x: 250, y: 300, width: 100, height: 100))
        view21.drawRoundCorner(cornerOrigin: [.bottomLeft,.bottomRight, .topLeft, .topRight], cornerRadius: 20)
        view21.backgroundColor = UIColor.orange

        view21.layer.shadowColor = UIColor.black.withAlphaComponent(0.3).cgColor
        view21.layer.shadowRadius = 10
        view21.layer.shadowOpacity = 1
        
        view.addSubview(view21)
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
    }
}

// Present the view controller in the Live View window
PlaygroundPage.current.liveView = MyViewController()
上一篇 下一篇

猜你喜欢

热点阅读