绘制两个CAShapeLayer的交点

时间:2018-10-05 14:16:17

标签: ios swift core-graphics

我正在尝试使用UIGraphicsImageRendererCGBlendModes将两个CALayer交点绘制到UIImage上,但没有成功。我尝试了所有具有不同图层位置的混合模式,但我几乎卡住了。

这是执行此操作的好方法还是其他方法?

我想实现的目标

Code preview

这是游乐场代码示例

import UIKit
import PlaygroundSupport

func getDesignElementLayer(byElementID elementID : Int) -> CAShapeLayer
{
    let caShapeLayer = CAShapeLayer()
    caShapeLayer.frame = CGRect(x: 0.0, y: 0.0, width: 100.0, height: 100.0)
    caShapeLayer.fillColor = UIColor.black.cgColor

    switch elementID
    {
    case 1:
        let ovalPath = UIBezierPath(ovalIn: CGRect(x: 0, y: 0, width: 100, height: 100))
        caShapeLayer.path = ovalPath.cgPath
    case 2:
        let bezierPath = UIBezierPath()

        bezierPath.move(to: (CGPoint(x: 50, y: 0)))
        bezierPath.addLine(to: (CGPoint(x: 0, y: 100)))
        bezierPath.addLine(to: (CGPoint(x: 100, y: 100)))
        bezierPath.addLine(to: (CGPoint(x: 50, y: 0)))
        bezierPath.close()
        caShapeLayer.path = bezierPath.cgPath

    default:
        print("")
    }

    return caShapeLayer
}

class MyViewController : UIViewController
{

    var shape1 : CAShapeLayer!
    var shape2 : CAShapeLayer!

    var testView : UIView!

    override func loadView() {
        let view = UIView()

        view.backgroundColor = .white
        shape1 = getDesignElementLayer(byElementID: 1)
        shape1.fillColor = UIColor.green.cgColor
        shape2 = getDesignElementLayer(byElementID: 2)
        shape2.fillColor = UIColor.yellow.cgColor

        view.layer.addSublayer(shape1)
        view.layer.addSublayer(shape2)


        let imageView = UIImageView(frame: CGRect(x: 0.0, y: 150.0, width: 100.0, height: 100.0))
        imageView.image = render()
        view.addSubview(imageView)
        self.view = view
    }

    func render() -> UIImage
    {
        let resolution = CGSize(width: 100.0, height: 100.0)
        let imageRenderer = UIGraphicsImageRenderer(size: resolution)
        let image = imageRenderer.image { (context) in

            shape1.render(in: context.cgContext)
            context.cgContext.setBlendMode(.clear)
            shape2.render(in: context.cgContext)
        }
        return image
    }
}
// Present the view controller in the Live View window
PlaygroundPage.current.liveView = MyViewController()

编辑:CALayers可以将图像作为内容,因此示例中的CAShapeLayers仅作为示例。我需要找到任何类型的CALayers的交集。

1 个答案:

答案 0 :(得分:0)

您可以通过剪切cgPaths而不是形状图层来实现此目的。

这是一个游乐场示例:

import UIKit
import PlaygroundSupport

func getDesignElementPath(byElementID elementID : Int) -> CGPath
{
    var pth: CGPath!

    switch elementID
    {
    case 1:
        let ovalPath = UIBezierPath(ovalIn: CGRect(x: 0, y: 0, width: 100, height: 100))
        pth = ovalPath.cgPath
    case 2:
        let bezierPath = UIBezierPath()

        bezierPath.move(to: (CGPoint(x: 50, y: 0)))
        bezierPath.addLine(to: (CGPoint(x: 0, y: 100)))
        bezierPath.addLine(to: (CGPoint(x: 100, y: 100)))
        bezierPath.addLine(to: (CGPoint(x: 50, y: 0)))
        bezierPath.close()
        pth = bezierPath.cgPath

    default:
        print("")
    }

    return pth
}

class MyViewController : UIViewController
{
    override func loadView() {
        let view = UIView()

        view.backgroundColor = .white

        let img = renderTest()

        let imageView = UIImageView(image: img)
        imageView.frame.origin = CGPoint(x: 40, y: 40)
        view.addSubview(imageView)

        self.view = view
    }

    func renderTest() -> UIImage {

        let size = CGSize(width: 100.0, height: 100.0)

        UIGraphicsBeginImageContext(size)

        guard let ctx = UIGraphicsGetCurrentContext() else { return UIImage() }

        let circle = getDesignElementPath(byElementID: 1)
        let triangle = getDesignElementPath(byElementID: 2)

        ctx.addPath(circle)
        ctx.clip()

        ctx.addPath(triangle)
        ctx.clip()

        ctx.setFillColor(UIColor.yellow.cgColor)
        ctx.fill(CGRect(x: 0, y: 0, width: size.width, height: size.height))

        let image = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()

        return image!
    }

}
// Present the view controller in the Live View window
PlaygroundPage.current.liveView = MyViewController()

结果:

enter image description here


编辑:

如果您想使用该形状裁剪图像,则可以将其用作遮罩。

与上述代码相同,但将viewDidLoad()替换为:

override func loadView() {
    let view = UIView()

    view.backgroundColor = .white

    // load a 100x100 image (of a cat)
    let imgForLayer = UIImage(named: "cat100x100.jpg")

    // create a 100x100 UIView at x:40 y:40
    let testView = UIView(frame: CGRect(x: 40.0, y: 40.0, width: 100.0, height: 100.0))

    // create an "image layer"
    let imgLayer = CALayer()
    // set its frame to match the view
    imgLayer.frame = testView.bounds
    // set its contents to the "cat" image
    imgLayer.contents = imgForLayer?.cgImage
    // add it as an "image sub layer"
    testView.layer.addSublayer(imgLayer)

    // create image with triangle / oval clip path
    let img = renderTest()

    // create a UIImageView from the rendered image
    let maskImageView = UIImageView(image: img)

    // use that image view as a mask
    testView.mask = maskImageView

    // add testView to the view
    view.addSubview(testView)

    self.view = view
}

猫图片:

enter image description here

结果:

enter image description here