1. Introduction

Do not do what fancy, how to use the system API to quickly achieve scratch-off.

2. The actual combat

Idea: through the mask to achieve the effect of scraping. The scraping process can be transformed into a drawing process.

2.1 Subclass UIPanGestureRecognizer

class SNXPanGestureRecognizer: UIPanGestureRecognizer {
    var touchBeganLocation: CGPoint?
    
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent) {
        super.touchesBegan(touches, with: event)
        touchBeganLocation = touches.first?.location(in: view)
    }
}
Copy the code

Why subclass UIPanGestureRecognizer?

Because UIPanGestureRecognizer in recognition when there is a recognition distance, if from UIGestureRecognizer State. Began to record, would have lost a key point, cause it is not from his starting place.

2.2 Scratch-off view

Create a two-tier view:

  • coverViewOn the bottom, you can use solid colors, or your favorite scratch-off cover image.
  • imageViewIn the upper. Because the back is covered with a transparent layer, you can’t see what’s inside, just like the scratch-off cover. When we draw the pattern, the part of the pattern will be shown and obscuredcoverViewIt’s like it’s been blown out.
// Cover view
let coverView: UIView = UIView()
coverView.backgroundColor = UIColor.gray
coverView.frame = CGRect(x: 0, y: 0, width: 350, height: 235)
coverView.center = view.center
view.addSubview(coverView)
// First prize picture
let imageView: UIImageView = UIImageView()
imageView.frame = coverView.frame
imageView.image = UIImage(named: "prize")
imageView.contentMode = .scaleAspectFill
view.addSubview(imageView)
Copy the code

The code for the mask layer is also simple. Once the required parameters are configured, add a mask to the imageView.

// maskLayer is the VC instance variable and will be used later in the action callback
let maskLayer: CAShapeLayer = CAShapeLayer(a)/ / montmorillonite layer
maskLayer.frame = imageView.bounds
maskLayer.lineWidth = 8.0
maskLayer.lineCap = CAShapeLayerLineCap.round
maskLayer.lineJoin = CAShapeLayerLineJoin.round
maskLayer.strokeColor = UIColor.black.cgColor
maskLayer.fillColor = UIColor.clear.cgColor
imageView.layer.mask = maskLayer
Copy the code

We added the gesture to coverView.

ImageView doesn’t respond to gestures by default, so I added coverView here.

This is where you can add to your favorite view based on your personal preference.

/ / gestures
let panGes: SNXPanGestureRecognizer = SNXPanGestureRecognizer(target: self, action: #selector(panGesHandler(_:)))
coverView.addGestureRecognizer(panGes)
Copy the code

The response code is also simple.

UIGestureRecognizer. State. Began to mobile users start touch points, then the addLine (to) the coordinates of gesture recognition, is the part of users start up. Then call addLine(to:) repeatedly to complete the drawing. Finally, update the path to the maskLayer.

// Path is the VC instance variable
let path: UIBezierPath = UIBezierPath(a)@objc func panGesHandler(_ recognizer: SNXPanGestureRecognizer) {
    switch recognizer.state {
    case .began:
        if let touchBeganLocation = recognizer.touchBeganLocation {
            path.move(to: touchBeganLocation)
        }
        fallthrough
    case .changed, .ended, .cancelled:
        path.addLine(to: recognizer.location(in: recognizer.view))
    default:
        break
    }
    maskLayer.path = path.cgPath
}
Copy the code

2.3 Complete Code

class ViewController: UIViewController {
    let maskLayer: CAShapeLayer = CAShapeLayer(a)let path: UIBezierPath = UIBezierPath(a)override func viewDidLoad(a) {
        super.viewDidLoad()
        // Cover view
        let coverView: UIView = UIView()
        coverView.backgroundColor = UIColor.gray
        coverView.frame = CGRect(x: 0, y: 0, width: 350, height: 235)
        coverView.center = view.center
        view.addSubview(coverView)
        // First prize picture
        let imageView: UIImageView = UIImageView()
        imageView.frame = coverView.frame
        imageView.image = UIImage(named: "prize")
        imageView.contentMode = .scaleAspectFill
        view.addSubview(imageView)
        / / montmorillonite layer
        maskLayer.frame = imageView.bounds
        maskLayer.lineWidth = 8.0
        maskLayer.lineCap = CAShapeLayerLineCap.round
        maskLayer.lineJoin = CAShapeLayerLineJoin.round
        maskLayer.strokeColor = UIColor.black.cgColor
        maskLayer.fillColor = UIColor.clear.cgColor
        imageView.layer.mask = maskLayer
        / / gestures
        let panGes: SNXPanGestureRecognizer = SNXPanGestureRecognizer(target: self, action: #selector(panGesHandler(_:)))
        coverView.addGestureRecognizer(panGes)
    }

    @objc func panGesHandler(_ recognizer: SNXPanGestureRecognizer) {
        switch recognizer.state {
        case .began:
            if let touchBeganLocation = recognizer.touchBeganLocation {
                path.move(to: touchBeganLocation)
            }
            fallthrough
        case .changed, .ended, .cancelled:
            path.addLine(to: recognizer.location(in: recognizer.view))
        default:
            break
        }
        maskLayer.path = path.cgPath
    }
}
Copy the code

If you like this article, give me a thumbs up ~ ❤️