简体   繁体   English

如何在 Swift 中使用 CAShapeLayer 在正方形的角上画一条线

[英]How to draw a line at the corner of a square with CAShapeLayer in Swift

I am developing a face recognition application of Vision library, and I am having trouble drawing lines with CAShapeLayer我正在开发 Vision 库的人脸识别应用程序,但在使用 CAShapeLayer 绘制线条时遇到问题

here is the code after getting camera output:这是获取相机output后的代码:

func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) {
        guard let imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer) else {
            return
        }
        
        let imageRequestHandler = VNImageRequestHandler(cvPixelBuffer: imageBuffer, orientation: .leftMirrored, options: [:])
        
        let faceDetectionRequest = VNDetectFaceLandmarksRequest(completionHandler: { (request: VNRequest, error: Error?) in
            DispatchQueue.main.async {
                self.faceLayers.forEach({ drawing in drawing.removeFromSuperlayer() })
                
                if let observations = request.results as? [VNFaceObservation] {
                    for observation in observations {
                        let faceRectConverted = self.videoPreviewLayer.layerRectConverted(fromMetadataOutputRect: observation.boundingBox)
                        let faceRectanglePath = CGPath(rect: faceRectConverted, transform: nil)
                        
                        let faceLayer = CAShapeLayer()
                        faceLayer.path = faceRectanglePath
                        faceLayer.fillColor = UIColor.clear.cgColor
                        faceLayer.strokeColor = UIColor.systemPink.cgColor
                        
                        self.faceLayers.append(faceLayer)
                        self.cameraView.layer.addSublayer(faceLayer)
                    }
                }
            }
        })
        
        do {
            try imageRequestHandler.perform([faceDetectionRequest])
        } catch {
            print(error.localizedDescription)
        }
    }

result结果

在此处输入图像描述

the problem I am facing when I want to draw a short line at the corner of the square当我想在正方形的角落画一条短线时我面临的问题

在此处输入图像描述

Thanks for all the support!感谢所有的支持!

You can use this:你可以使用这个:

let thinLayer = CAShapeLayer()
thinLayer.path = CGPath(rect: rect, transform: nil)
thinLayer.strokeColor = UIColor.purple.cgColor
thinLayer.fillColor = UIColor.clear.cgColor
thinLayer.lineWidth = 1.0
view.layer.addSublayer(thinLayer)

let cornerWidth: CGFloat = 20.0

let topLeftBezierPath = UIBezierPath()
topLeftBezierPath.move(to: CGPoint(x: rect.origin.x, y: rect.origin.y + cornerWidth))
topLeftBezierPath.addLine(to: CGPoint(x: rect.origin.x, y: rect.origin.y))
topLeftBezierPath.addLine(to: CGPoint(x: rect.origin.x + cornerWidth, y: rect.origin.y))

let topRightBezierPath = UIBezierPath()
topRightBezierPath.move(to: CGPoint(x: rect.maxX, y: rect.origin.y + cornerWidth))
topRightBezierPath.addLine(to: CGPoint(x: rect.maxX, y: rect.origin.y))
topRightBezierPath.addLine(to: CGPoint(x: rect.maxX - cornerWidth, y: rect.origin.y))


let bottomRightBezierPath = UIBezierPath()
bottomRightBezierPath.move(to: CGPoint(x: rect.maxX, y: rect.maxY - cornerWidth))
bottomRightBezierPath.addLine(to: CGPoint(x: rect.maxX, y: rect.maxY))
bottomRightBezierPath.addLine(to: CGPoint(x: rect.maxX - cornerWidth, y: rect.maxY))


let bottomLeftBezierPath = UIBezierPath()
bottomLeftBezierPath.move(to: CGPoint(x: rect.origin.x, y: rect.maxY - cornerWidth))
bottomLeftBezierPath.addLine(to: CGPoint(x: rect.origin.x, y: rect.maxY))
bottomLeftBezierPath.addLine(to: CGPoint(x: rect.origin.x + cornerWidth, y: rect.maxY))


func cornerLayer(with bezierPath: UIBezierPath) -> CAShapeLayer {
    let shape = CAShapeLayer()
    shape.path = bezierPath.cgPath
    shape.lineWidth = 4.0
    shape.strokeColor = UIColor.purple.cgColor
    shape.fillColor = UIColor.clear.cgColor
    shape.lineCap = .round
    return shape
}


let topLeftShape = cornerLayer(with: topLeftBezierPath)
view.layer.addSublayer(topLeftShape)

let topRightShape = cornerLayer(with: topRightBezierPath)
view.layer.addSublayer(topRightShape)

let bottomRightShape = cornerLayer(with: bottomRightBezierPath)
view.layer.addSublayer(bottomRightShape)

let bottomLeftShape = cornerLayer(with: bottomLeftBezierPath)
view.layer.addSublayer(bottomLeftShape)

Where:在哪里:

  • view is the UIView on which to add the layer, in your case it's cameraView . view是要在其上添加图层的UIView ,在您的情况下是cameraView
  • rect is the full rect of the face, in your case it's faceRectConverted rect是脸部的完整矩形,在您的情况下是faceRectConverted
  • customize to fulfill your needs ( lineWidh , strokeColor , cornerWidth which might me proportional to the size of the rect?)定制以满足您的需求( lineWidhstrokeColorcornerWidth ,我可能与矩形的大小成正比?)

Sample in Playground:游乐场样本:

func drawing() -> UIView {
    let view = UIView(frame: CGRect(x: 0, y: 0, width: 300, height: 300))
    view.backgroundColor = .orange

    let rect = CGRect(x: 50, y: 50, width: 200, height: 200)

    let thinLayer = CAShapeLayer()
    thinLayer.path = CGPath(rect: rect, transform: nil)
    thinLayer.strokeColor = UIColor.purple.cgColor
    thinLayer.fillColor = UIColor.clear.cgColor
    thinLayer.lineWidth = 1.0
    view.layer.addSublayer(thinLayer)

    let cornerWidth: CGFloat = 20.0

    let topLeftBezierPath = UIBezierPath()
    topLeftBezierPath.move(to: CGPoint(x: rect.origin.x, y: rect.origin.y + cornerWidth))
    topLeftBezierPath.addLine(to: CGPoint(x: rect.origin.x, y: rect.origin.y))
    topLeftBezierPath.addLine(to: CGPoint(x: rect.origin.x + cornerWidth, y: rect.origin.y))

    let topRightBezierPath = UIBezierPath()
    topRightBezierPath.move(to: CGPoint(x: rect.maxX, y: rect.origin.y + cornerWidth))
    topRightBezierPath.addLine(to: CGPoint(x: rect.maxX, y: rect.origin.y))
    topRightBezierPath.addLine(to: CGPoint(x: rect.maxX - cornerWidth, y: rect.origin.y))


    let bottomRightBezierPath = UIBezierPath()
    bottomRightBezierPath.move(to: CGPoint(x: rect.maxX, y: rect.maxY - cornerWidth))
    bottomRightBezierPath.addLine(to: CGPoint(x: rect.maxX, y: rect.maxY))
    bottomRightBezierPath.addLine(to: CGPoint(x: rect.maxX - cornerWidth, y: rect.maxY))


    let bottomLeftBezierPath = UIBezierPath()
    bottomLeftBezierPath.move(to: CGPoint(x: rect.origin.x, y: rect.maxY - cornerWidth))
    bottomLeftBezierPath.addLine(to: CGPoint(x: rect.origin.x, y: rect.maxY))
    bottomLeftBezierPath.addLine(to: CGPoint(x: rect.origin.x + cornerWidth, y: rect.maxY))


    func cornerLayer(with bezierPath: UIBezierPath) -> CAShapeLayer {
        let shape = CAShapeLayer()
        shape.path = bezierPath.cgPath
        shape.lineWidth = 4.0
        shape.strokeColor = UIColor.purple.cgColor
        shape.fillColor = UIColor.clear.cgColor
        shape.lineCap = .round
        return shape
    }


    let topLeftShape = cornerLayer(with: topLeftBezierPath)
    view.layer.addSublayer(topLeftShape)

    let topRightShape = cornerLayer(with: topRightBezierPath)
    view.layer.addSublayer(topRightShape)

    let bottomRightShape = cornerLayer(with: bottomRightBezierPath)
    view.layer.addSublayer(bottomRightShape)

    let bottomLeftShape = cornerLayer(with: bottomLeftBezierPath)
    view.layer.addSublayer(bottomLeftShape)

    return view
}

let drawn = drawing()

drawn

Output: Output:

在此处输入图像描述

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM