当前位置:网站首页>2- use line segments to form graphics and coordinate conversion

2- use line segments to form graphics and coordinate conversion

2022-06-23 08:24:00 the Summer Palace

This article uses a custom checkbox Example of a button , Show me how to use Core Graphics The multi line drawing function of the drawing control UI .

CheckButton

First create CheckButton class :

// 1
class CheckButton: ShadowButton {
    override init(frame: CGRect) {
        super.init(frame: frame)
        commonInit()
    }
    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        commonInit()
    }
    // 2
    fileprivate func commonInit() {
        text = nil
    }
    // 3
    override public func selectDraw(_ frame: CGRect) {

        // 4
        super.selectDraw(frame)
        // 5
        let selectedColor = UIColor(red: 0, green: 249/255, blue: 192/255, alpha: 1)
        LinePainter.drawCheckMark(selectedColor, targetFrame: frame, shadow: outerShadow)
    }
	// 6
    override public func unselectDraw(_ frame: CGRect) {

        super.unselectDraw(frame)

        LinePainter.drawCheckMark(.white, targetFrame: frame, shadow: outerShadow)
    }
}
extension CheckButton {

    // 7
    override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
        isSelected = !isSelected
        setNeedsDisplay()
    }
    // 8
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {}
}
 
  1. CheckButton Inherited ShadowButton, Because it also wants to have ShadowButton The inner and outer shadows of 、 Fill the gradient of the background 、 Attributes such as fillet radius .
  2. commonInit In the method , We will text Property is empty , Because it doesn't need to display text .
  3. drawSelect Method , Draw function when selected .
  4. First , Call inherited drawSelect Method .
  5. And then call LinePainter Draw a green check mark for us to indicate the check .
  6. Cover unselectDraw Method . Draw unselected state , Follow selectDraw In the same way , The only difference is that the color of the tick is changed to white .
  7. touchBegan Method , Handle the touch of the button , For one checkbox Control , Let it in select/unselect Just switch between .
  8. touchEnded Method null implementation , Because we don't want to release the effect of state restoration after touch .

LinePainter

LinePainter It's the first time we met 3 individual Painter, It provides a method for drawing multi line segments , And how to draw a tick for us .

class LinePainter {
    private let context: CGContext?

    init() {
        self.context =  UIGraphicsGetCurrentContext()
    }
    // 1.
    func polyLines(_ points: [CGPoint]) -> UIBezierPath {
        let path = UIBezierPath()

        for i in 0..<points.count {
            if i == 0 {
                path.move(to: points[0])
            }else{
                path.addLine(to: points[i])
            }
        }
        return path
    }
    
    // 2
    func drawCheckMark(_ color: UIColor, targetFrame: CGRect, shadow: NSShadow?) {
        if let context = context {

            // 3
  
            let originFrame = CGRect(x: 75, y: 22, width: 96, height: 96)
            let vertex1 = convert(CGPoint(x: 100, y: 78),originFrame: originFrame, newFrame: targetFrame)
            let vertex2 = convert(CGPoint(x: 117, y: 92), originFrame: originFrame,newFrame: targetFrame)
            let vertex3 = convert(CGPoint(x: 151, y: 48), originFrame: originFrame, newFrame: targetFrame)
            
            // 4
            let path = polyLines([vertex1, vertex2, vertex3])
            
            context.saveGState()
            // 5
            if let shadow = shadow {
                context.setShadow(offset: shadow.shadowOffset, blur: shadow.shadowBlurRadius, color: (shadow.shadowColor as! UIColor).cgColor)
            }
            // 6
            color.setStroke()
            // 7
            path.lineWidth = 7
            // 8
            path.lineJoinStyle = .round
            // 9
            path.stroke()
            context.restoreGState()

        }
    }
    
    // 10
    private func convert(_ point: CGPoint, originFrame: CGRect, newFrame: CGRect) -> CGPoint {
        let x:CGFloat = (point.x - originFrame.minX)/originFrame.width*newFrame.width + newFrame.minX
        let y:CGFloat = (point.y - originFrame.minY)/originFrame.height*newFrame.height + newFrame.minY
        return CGPoint(x:x, y: y)
    }
}

  1. polyLines Draw a polyline , The parameter is one CGPoint Array . The so-called multi line segment is actually a broken line connected by multiple points . So the drawing of multi line segment is essentially a vertex ( Endpoint ) The draw .polyLines The function returns a CGPath.
  2. Draw a tick by drawing multiple line segments .
  3. A tick consists of three vertices , We calculate these respectively 3 vertices . The calculation of each vertex is a call to convert Function .
  4. Pass three vertices into polyLines function , So we can calculate a two-dimensional figure ( Tick ).
  5. If there is a shadow , Add shadow when painting .
  6. Set the drawing path to color .
  7. Set the line width .
  8. Set vertex fillet .
  9. Drawing graphics .
  10. convert The function calculates vertex coordinates . The coordinates on the design drawing need to be converted to get the coordinates of the control itself . Take the example here , The coordinates of the first point 75,22 Is the coordinates taken from the canvas on the design drawing ( You can use it. sketch). It first needs to subtract the coordinates of the upper left corner of the control in the canvas , Then multiply by the scale of the button ( That is, the size of the control in the original drawing divided by the added to view Future actual size ), Plus the control is put into view after frame The origin coordinates of , To finally convert to the correct coordinates .

test

stay viewDidLoad in :

		 let button = CheckButton(frame: CGRect(x: 100, y: 200, width: 100, height: 100))
        button.gradient = gradient()
        button.outerShadow = outerShadow()
        button.innerShadow = innerShadow()
        button.buttonRadius = 11
        
        button.backgroundColor = .white
        button.layer.cornerRadius = 20
        
        addSubview(button)
原网站

版权声明
本文为[the Summer Palace]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/174/202206230756065495.html