วิธีครอบตัด UIImage เพื่อมาส์กใน Swift

ฉันมี UIImage ที่ฉันปกปิดโดยใช้ UIImage อื่น ปัญหาเดียวคือพื้นที่นอก UIImage ที่มาสก์ยังคงสามารถโต้ตอบกับผู้ใช้ได้ ฉันจะครอบตัด UIImage ให้เป็นรูปภาพอื่นแทนการมาสก์ได้อย่างไร

@IBOutlet weak var imageView: UIImageView!

override func viewDidLoad() {
    super.viewDidLoad()
    let imageMask = UIImageView()

    imageMask.image = //image to mask

    imageMask.frame = photoImageView.bounds
    imageView.mask = imageMask
}

ป้อนคำอธิบายรูปภาพที่นี่ ป้อนคำอธิบายรูปภาพที่นี่


person Cristian    schedule 20.11.2018    source แหล่งที่มา
comment
stackoverflow.com/questions/32041420/ ฉันคิดว่าคำถามนี้คล้ายกัน   -  person Ruban4Axis    schedule 20.11.2018


คำตอบ (1)


เกณฑ์

กรณีทดสอบอย่างง่ายสามารถกำหนดสีพื้นหลังสำหรับมุมมองของ ViewController และโหลดรูปภาพและมาสก์ จากนั้น UITapGestureRecognizer จะถูกเพิ่มในมุมมอง ViewController และใน UIImageView

เมื่อใช้สีพื้นหลังกับมุมมอง ViewController จะง่ายต่อการดูว่าการมาสก์ใช้งานได้หรือไม่

หากคุณแตะบนพื้นที่ที่ไม่โปร่งใส UIImageView ควรได้รับการแตะ มิฉะนั้นมุมมอง ViewController ควรได้รับการแตะ

ขนาดรูปภาพและมาสก์

ในกรณีส่วนใหญ่ ขนาดรูปภาพและรูปภาพมาสก์หรืออย่างน้อยก็อัตราส่วนภาพของรูปภาพและรูปภาพมาสก์จะเท่ากัน มันสมเหตุสมผลที่จะใช้ contentMode เดียวกันสำหรับการมาสก์ของ UIImageView เช่นเดียวกับ UIImageView ดั้งเดิม มิฉะนั้นจะมีการวางแนวที่ไม่ตรงเมื่อเปลี่ยนโหมดเนื้อหาใน InterfaceBuilder เป็นอย่างล่าสุด

กรณีทดสอบ

ดังนั้นกรณีทดสอบอาจมีลักษณะดังนี้:

import UIKit

class ViewController: UIViewController {

    @IBOutlet weak var imageView: UIImageView!
    private let maskView = UIImageView()

    override func viewDidLoad() {
        super.viewDidLoad()
        self.imageView.image = UIImage(named: "testimage")
        self.maskView.image = UIImage(named: "mask")
        self.imageView.mask = maskView

        let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(backgroundTapped))
        self.view.addGestureRecognizer(tapGestureRecognizer)

        let imageViewGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(iamgeViewTapped))
        self.imageView.addGestureRecognizer(imageViewGestureRecognizer)
    }

    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
        self.maskView.contentMode = self.imageView.contentMode
        self.maskView.frame = self.imageView.bounds
    }

    @objc private func backgroundTapped() {
        print ("background tapped!")
    }

    @objc private func iamgeViewTapped() {
        print ("image view tapped!")
    }

}

รหัสนี้กำลังทำงานอยู่แล้ว ตามที่คาดไว้ การแตะที่พื้นที่โปร่งใสของ UIImageView ก็มาถึงที่นี่เช่นกัน

CustomImageView

ดังนั้นเราจึงจำเป็นต้องมี CustomImageView ซึ่งจะส่งคืนเมื่อคลิกที่พิกเซลโปร่งใสซึ่งจะไม่รับผิดชอบ

ซึ่งสามารถทำได้โดยการแทนที่วิธีนี้:

func point(inside point: CGPoint, 
      with event: UIEvent?) -> Bool

ดูเอกสารที่นี่: https://developer.apple.com/documentation/uikit/uiview/1622533-point

ส่งกลับค่าบูลีนที่ระบุว่าผู้รับมีจุดที่ระบุหรือไม่

มีคำตอบที่ยอดเยี่ยมนี้อยู่แล้วใน SO ซึ่งปรับเปลี่ยนเล็กน้อย: https://stackoverflow.com/a/27923457

import UIKit

class CustomImageView: UIImageView {

    override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
        return self.alphaFromPoint(point: point) > 32
    }

    private func alphaFromPoint(point: CGPoint) -> UInt8 {
        var pixel: [UInt8] = [0, 0, 0, 0]
        let colorSpace = CGColorSpaceCreateDeviceRGB();
        let alphaInfo = CGBitmapInfo(rawValue: CGImageAlphaInfo.premultipliedLast.rawValue)
        if let context = CGContext(data: &pixel,
                                   width: 1,
                                   height: 1,
                                   bitsPerComponent: 8,
                                   bytesPerRow: 4,
                                   space: colorSpace,
                                   bitmapInfo: alphaInfo.rawValue) {
            context.translateBy(x: -point.x, y: -point.y)
            self.layer.render(in: context)
        }
        return pixel[3]
    }

}

อย่าลืมเปลี่ยนคลาสที่กำหนดเองของ ImageView เป็น CustomImageView ใน Xcode ในตัวตรวจสอบข้อมูลประจำตัว

หากคุณแตะที่พื้นที่โปร่งใส มุมมองของ ViewController ในพื้นหลังจะได้รับการแตะ หากคุณแตะที่พื้นที่ที่ไม่โปร่งใส มุมมองรูปภาพของเราจะได้รับการแตะ

สาธิต

นี่คือตัวอย่างสั้นๆ ของโค้ดด้านบนโดยใช้รูปภาพและมาสก์จากคำถาม:

สาธิต

person Stephan Schlecht    schedule 02.12.2018
comment
ขอบคุณนี่ตอบคำถามของฉันอย่างแน่นอน - person Cristian; 02.12.2018